{"action":"created","comment":{"url":"https://api.github.com/repos/iotaledger/entangled/pulls/comments/231891597","pull_request_review_id":172961307,"id":231891597,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMTg5MTU5Nw==","diff_hunk":"@@ -6,219 +6,278 @@\n  */\n \n #include \"gossip/components/responder.h\"\n-#include \"ciri/core.h\"\n-#include \"common/storage/sql/defs.h\"\n #include \"gossip/neighbor.h\"\n-#include \"utils/containers/queues/concurrent_queue_transaction_request.h\"\n+#include \"gossip/node.h\"\n+#include \"utils/handles/rand.h\"\n #include \"utils/logger_helper.h\"\n \n-#define RESPONDER_COMPONENT_LOGGER_ID \"responder_component\"\n+#define RESPONDER_LOGGER_ID \"responder\"\n+#define RESPONDER_TIMEOUT_SEC 1\n \n-static retcode_t random_tip_request(transaction_request_t *const request) {\n-  // TODO(thibault): Random tip request\n-  request->neighbor->nbr_random_tx_req++;\n-  return RC_OK;\n-}\n+/**\n+ * Private functions\n+ */\n \n-static retcode_t regular_transaction_request(\n-    responder_state_t *const state, transaction_request_t *const request,\n-    iota_transaction_t *const tx) {\n+/**\n+ * Gets a transaction according to a request hash\n+ * - if null hash: gets a random tip\n+ * - if non-null hash: gets the corresponding transaction\n+ *\n+ * @param responder The responder\n+ * @param neighbor The requesting neighbor\n+ * @param hash The request hash\n+ * @param pack A stor pack to be filled with a transaction\n+ *\n+ * @return a status code\n+ */\n+static retcode_t get_transaction_for_request(responder_t const *const responder,\n+                                             neighbor_t *const neighbor,\n+                                             trit_array_t const *const hash,\n+                                             iota_stor_pack_t *const pack) {\n   retcode_t ret = RC_OK;\n \n-  if ((*tx = transaction_new()) == NULL) {\n-    return RC_RESPONDER_COMPONENT_OOM;\n+  if (responder == NULL || neighbor == NULL || hash == NULL || pack == NULL) {\n+    return RC_NULL_PARAM;\n   }\n \n-  iota_stor_pack_t pack = {.models = (void **)tx,\n-                           .capacity = 1,\n-                           .num_loaded = 0,\n-                           .insufficient_capacity = false};\n-  if ((ret = iota_tangle_transaction_load(state->tangle, TRANSACTION_FIELD_HASH,\n-                                          request->hash, &pack))) {\n-    return ret;\n+  // If the hash is null, a random tip was requested\n+  if (flex_trits_are_null(hash->trits, FLEX_TRIT_SIZE_243)) {\n+    log_debug(RESPONDER_LOGGER_ID, \"Responding to random tip request\\n\");\n+    if (true) {\n+      // TODO random tip request\n+      neighbor->nbr_random_tx_req++;\n+    }\n+    // Else no tx to request, so no random tip will be sent as a reply.\n   }\n-  if (pack.num_loaded == 0) {\n-    transaction_free(*tx);\n-    *tx = NULL;\n+  // If the hash is non-null, a transaction was requested\n+  else {\n+    log_debug(RESPONDER_LOGGER_ID,\n+              \"Responding to regular transaction request\\n\");\n+    if ((ret = iota_tangle_transaction_load(\n+             responder->tangle, TRANSACTION_FIELD_HASH, hash, pack)) != RC_OK) {\n+      log_warning(RESPONDER_LOGGER_ID, \"Loading transaction failed\\n\");\n+      return ret;\n+    }\n   }\n-  return RC_OK;\n-}\n \n-static retcode_t get_transaction_for_request(\n-    responder_state_t *const state, transaction_request_t *const request,\n-    iota_transaction_t *const tx) {\n-  if (state == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_STATE;\n-  } else if (request == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_REQ;\n-  } else if (request->neighbor == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_NEIGHBOR;\n-  } else if (tx == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_TX;\n-  }\n-\n-  if (trit_array_is_null(request->hash)) {\n-    log_debug(RESPONDER_COMPONENT_LOGGER_ID,\n-              \"Responding to random tip request\\n\");\n-    return random_tip_request(request);\n-  }  // else\n-  log_debug(RESPONDER_COMPONENT_LOGGER_ID,\n-            \"Responding to regular transaction request\\n\");\n-  return regular_transaction_request(state, request, tx);\n+  return ret;\n }\n \n-static retcode_t reply_to_request(responder_state_t *const state,\n-                                  transaction_request_t *const request,\n-                                  iota_transaction_t const tx) {\n+/**\n+ * Responds to a request by:\n+ * - sending a transaction to the requesting neighbor or\n+ * - requesting a missing transaction\n+ *\n+ * @param responder The responder\n+ * @param neighbor The requesting neighbor\n+ * @param hash The request hash\n+ * @param pack A stor pack containing a transaction\n+ *\n+ * @return a status code\n+ */\n+static retcode_t respond_to_request(responder_t const *const responder,\n+                                    neighbor_t *const neighbor,\n+                                    flex_trit_t const *const hash,\n+                                    iota_stor_pack_t *const pack) {\n   retcode_t ret = RC_OK;\n \n-  if (state == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_STATE;\n-  } else if (request == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_REQ;\n-  } else if (request->neighbor == NULL) {\n-    return RC_RESPONDER_COMPONENT_NULL_NEIGHBOR;\n+  if (responder == NULL || neighbor == NULL || hash == NULL || pack == NULL) {\n+    return RC_NULL_PARAM;\n   }\n \n-  if (tx != NULL) {\n-    // Send transaction back to neighbor\n-    flex_trit_t tx_trits[FLEX_TRIT_SIZE_8019];\n+  if (pack->num_loaded != 0) {\n+    // If a transaction or a random tip was found, sends it back to the neighbor\n+    iota_transaction_t transaction = ((iota_transaction_t *)(pack->models))[0];\n+    flex_trit_t transaction_flex_trits[FLEX_TRIT_SIZE_8019];\n \n-    transaction_serialize_on_flex_trits(tx, tx_trits);\n-    if ((ret = neighbor_send(state->node, request->neighbor, tx_trits)) !=\n-        RC_OK) {\n+    transaction_serialize_on_flex_trits(transaction, transaction_flex_trits);\n+    if ((ret = neighbor_send(responder->node, neighbor,\n+                             transaction_flex_trits)) != RC_OK) {\n+      log_warning(RESPONDER_LOGGER_ID, \"Sending transaction failed\\n\");\n       return ret;\n     }\n+    // TODO Add transaction to cache\n   } else {\n-    // Transaction not found\n-    // TODO(thibault): Randomly doesn't propagate request\n-    if (trit_array_is_null(request->hash) == false) {\n-      // Request is an actual missing transaction\n-      if ((ret = request_transaction(&state->node->transaction_requester,\n-                                     request->hash->trits, false)) != RC_OK) {\n+    // If a transaction was requested but not found, requests it\n+    if (!flex_trits_are_null(hash, FLEX_TRIT_SIZE_243) &&\n+        rand_handle_probability() < responder->node->conf.p_propagate_request) {\n+      if ((ret = request_transaction(&responder->node->transaction_requester,\n+                                     hash, false)) != RC_OK) {\n+        log_warning(RESPONDER_LOGGER_ID, \"Requesting transaction failed\\n\");\n         return ret;\n       }\n     }\n   }\n+\n   return RC_OK;\n }\n \n-static void *responder_routine(responder_state_t *const state) {\n-  transaction_request_t request;\n-  iota_transaction_t tx = NULL;\n+/**\n+ * Continuously looks for a transaction request from a responder queue and\n+ * process it\n+ *\n+ * @param responder The responder state\n+ */\n+static void *responder_routine(responder_t *const responder) {\n+  transaction_request_t *request = NULL;\n+  DECLARE_PACK_SINGLE_TX(tx, tx_ptr, pack);\n+  trit_array_t hash = {.trits = NULL,\n+                       .num_trits = HASH_LENGTH_TRIT,\n+                       .num_bytes = FLEX_TRIT_SIZE_243,\n+                       .dynamic = 0};\n \n-  if (state == NULL) {\n+  if (responder == NULL) {\n     return NULL;\n   }\n \n-  while (state->running) {\n-    if (CQ_POP(state->queue, &request) == CQ_SUCCESS) {\n-      log_debug(RESPONDER_COMPONENT_LOGGER_ID, \"Responding to request\\n\");\n-      if (get_transaction_for_request(state, &request, &tx)) {\n-        log_warning(RESPONDER_COMPONENT_LOGGER_ID,\n-                    \"Getting transaction for request failed\\n\");\n-        continue;\n-      }\n-      if (reply_to_request(state, &request, tx)) {\n-        log_warning(RESPONDER_COMPONENT_LOGGER_ID,\n-                    \"Replying to request failed\\n\");\n-        continue;\n-      }\n+  lock_handle_t lock_cond;\n+  lock_handle_init(&lock_cond);\n+  lock_handle_lock(&lock_cond);\n+\n+  while (responder->running) {\n+    if (responder_size(responder) == 0) {\n+      cond_handle_timedwait(&responder->cond, &lock_cond,\n+                            RESPONDER_TIMEOUT_SEC);\n+    }\n+    rw_lock_handle_wrlock(&responder->lock);\n+    request = transaction_request_queue_peek(responder->queue);\n+    if (request == NULL) {\n+      rw_lock_handle_unlock(&responder->lock);\n+      continue;\n+    }\n+    log_debug(RESPONDER_LOGGER_ID, \"Responding to request\\n\");\n+    hash_pack_reset(&pack);\n+    hash.trits = request->hash;\n+    if (get_transaction_for_request(responder, request->neighbor, &hash,\n+                                    &pack) != RC_OK) {\n+      log_warning(RESPONDER_LOGGER_ID,\n+                  \"Getting transaction for request failed\\n\");\n+    } else if (respond_to_request(responder, request->neighbor, request->hash,\n+                                  &pack) != RC_OK) {\n+      log_warning(RESPONDER_LOGGER_ID, \"Replying to request failed\\n\");\n     }\n+    transaction_request_queue_pop(&responder->queue);","path":"gossip/components/responder.c","position":239,"original_position":239,"commit_id":"ec15c796b1cb3c08d3cefaf4bea6b3abf02b5646","original_commit_id":"ec15c796b1cb3c08d3cefaf4bea6b3abf02b5646","user":{"login":"th0br0","id":30996,"node_id":"MDQ6VXNlcjMwOTk2","avatar_url":"https://avatars0.githubusercontent.com/u/30996?v=4","gravatar_id":"","url":"https://api.github.com/users/th0br0","html_url":"https://github.com/th0br0","followers_url":"https://api.github.com/users/th0br0/followers","following_url":"https://api.github.com/users/th0br0/following{/other_user}","gists_url":"https://api.github.com/users/th0br0/gists{/gist_id}","starred_url":"https://api.github.com/users/th0br0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/th0br0/subscriptions","organizations_url":"https://api.github.com/users/th0br0/orgs","repos_url":"https://api.github.com/users/th0br0/repos","events_url":"https://api.github.com/users/th0br0/events{/privacy}","received_events_url":"https://api.github.com/users/th0br0/received_events","type":"User","site_admin":false},"body":"If we don't have the requested tx in our DB we should add it to our own TX req queue I believe?\r\n\r\nEither way: we can pop instead of peek here as we always pop? (and thus reducing the time we hold the lock)","created_at":"2018-11-08T13:44:41Z","updated_at":"2018-11-08T13:44:44Z","html_url":"https://github.com/iotaledger/entangled/pull/484#discussion_r231891597","pull_request_url":"https://api.github.com/repos/iotaledger/entangled/pulls/484","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/iotaledger/entangled/pulls/comments/231891597"},"html":{"href":"https://github.com/iotaledger/entangled/pull/484#discussion_r231891597"},"pull_request":{"href":"https://api.github.com/repos/iotaledger/entangled/pulls/484"}}},"pull_request":{"url":"https://api.github.com/repos/iotaledger/entangled/pulls/484","id":228937905,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI4OTM3OTA1","html_url":"https://github.com/iotaledger/entangled/pull/484","diff_url":"https://github.com/iotaledger/entangled/pull/484.diff","patch_url":"https://github.com/iotaledger/entangled/pull/484.patch","issue_url":"https://api.github.com/repos/iotaledger/entangled/issues/484","number":484,"state":"open","locked":false,"title":"Responder refactoring","user":{"login":"thibault-martinez","id":3305068,"node_id":"MDQ6VXNlcjMzMDUwNjg=","avatar_url":"https://avatars1.githubusercontent.com/u/3305068?v=4","gravatar_id":"","url":"https://api.github.com/users/thibault-martinez","html_url":"https://github.com/thibault-martinez","followers_url":"https://api.github.com/users/thibault-martinez/followers","following_url":"https://api.github.com/users/thibault-martinez/following{/other_user}","gists_url":"https://api.github.com/users/thibault-martinez/gists{/gist_id}","starred_url":"https://api.github.com/users/thibault-martinez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thibault-martinez/subscriptions","organizations_url":"https://api.github.com/users/thibault-martinez/orgs","repos_url":"https://api.github.com/users/thibault-martinez/repos","events_url":"https://api.github.com/users/thibault-martinez/events{/privacy}","received_events_url":"https://api.github.com/users/thibault-martinez/received_events","type":"User","site_admin":false},"body":"- Changes queue to utash-based + cond/lock\r\n- Removes useless dynamic allocations & leaks\r\n- Uses `flex_trit_t *` instead of `trit_array_p`\r\n- Adds `p_propagate_request`\r\n- Adds `p_reply_random_tip`\r\n- Adds `p_send_milestone`\r\n- Nits & clean\r\n- Documentation\r\n- Adds a rand handle\r\n\r\nStill working on random tip request\r\n\r\n# Test Plan:\r\nCI must pass\r\n","created_at":"2018-11-07T07:22:27Z","updated_at":"2018-11-08T13:44:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ac3d056c590c53f4ed3538c0b6e8b185776cd6c6","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/iotaledger/entangled/pulls/484/commits","review_comments_url":"https://api.github.com/repos/iotaledger/entangled/pulls/484/comments","review_comment_url":"https://api.github.com/repos/iotaledger/entangled/pulls/comments{/number}","comments_url":"https://api.github.com/repos/iotaledger/entangled/issues/484/comments","statuses_url":"https://api.github.com/repos/iotaledger/entangled/statuses/ec15c796b1cb3c08d3cefaf4bea6b3abf02b5646","head":{"label":"thibault-martinez:responder-refactoring","ref":"responder-refactoring","sha":"ec15c796b1cb3c08d3cefaf4bea6b3abf02b5646","user":{"login":"thibault-martinez","id":3305068,"node_id":"MDQ6VXNlcjMzMDUwNjg=","avatar_url":"https://avatars1.githubusercontent.com/u/3305068?v=4","gravatar_id":"","url":"https://api.github.com/users/thibault-martinez","html_url":"https://github.com/thibault-martinez","followers_url":"https://api.github.com/users/thibault-martinez/followers","following_url":"https://api.github.com/users/thibault-martinez/following{/other_user}","gists_url":"https://api.github.com/users/thibault-martinez/gists{/gist_id}","starred_url":"https://api.github.com/users/thibault-martinez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thibault-martinez/subscriptions","organizations_url":"https://api.github.com/users/thibault-martinez/orgs","repos_url":"https://api.github.com/users/thibault-martinez/repos","events_url":"https://api.github.com/users/thibault-martinez/events{/privacy}","received_events_url":"https://api.github.com/users/thibault-martinez/received_events","type":"User","site_admin":false},"repo":{"id":137102070,"node_id":"MDEwOlJlcG9zaXRvcnkxMzcxMDIwNzA=","name":"entangled","full_name":"thibault-martinez/entangled","private":false,"owner":{"login":"thibault-martinez","id":3305068,"node_id":"MDQ6VXNlcjMzMDUwNjg=","avatar_url":"https://avatars1.githubusercontent.com/u/3305068?v=4","gravatar_id":"","url":"https://api.github.com/users/thibault-martinez","html_url":"https://github.com/thibault-martinez","followers_url":"https://api.github.com/users/thibault-martinez/followers","following_url":"https://api.github.com/users/thibault-martinez/following{/other_user}","gists_url":"https://api.github.com/users/thibault-martinez/gists{/gist_id}","starred_url":"https://api.github.com/users/thibault-martinez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thibault-martinez/subscriptions","organizations_url":"https://api.github.com/users/thibault-martinez/orgs","repos_url":"https://api.github.com/users/thibault-martinez/repos","events_url":"https://api.github.com/users/thibault-martinez/events{/privacy}","received_events_url":"https://api.github.com/users/thibault-martinez/received_events","type":"User","site_admin":false},"html_url":"https://github.com/thibault-martinez/entangled","description":null,"fork":true,"url":"https://api.github.com/repos/thibault-martinez/entangled","forks_url":"https://api.github.com/repos/thibault-martinez/entangled/forks","keys_url":"https://api.github.com/repos/thibault-martinez/entangled/keys{/key_id}","collaborators_url":"https://api.github.com/repos/thibault-martinez/entangled/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/thibault-martinez/entangled/teams","hooks_url":"https://api.github.com/repos/thibault-martinez/entangled/hooks","issue_events_url":"https://api.github.com/repos/thibault-martinez/entangled/issues/events{/number}","events_url":"https://api.github.com/repos/thibault-martinez/entangled/events","assignees_url":"https://api.github.com/repos/thibault-martinez/entangled/assignees{/user}","branches_url":"https://api.github.com/repos/thibault-martinez/entangled/branches{/branch}","tags_url":"https://api.github.com/repos/thibault-martinez/entangled/tags","blobs_url":"https://api.github.com/repos/thibault-martinez/entangled/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/thibault-martinez/entangled/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/thibault-martinez/entangled/git/refs{/sha}","trees_url":"https://api.github.com/repos/thibault-martinez/entangled/git/trees{/sha}","statuses_url":"https://api.github.com/repos/thibault-martinez/entangled/statuses/{sha}","languages_url":"https://api.github.com/repos/thibault-martinez/entangled/languages","stargazers_url":"https://api.github.com/repos/thibault-martinez/entangled/stargazers","contributors_url":"https://api.github.com/repos/thibault-martinez/entangled/contributors","subscribers_url":"https://api.github.com/repos/thibault-martinez/entangled/subscribers","subscription_url":"https://api.github.com/repos/thibault-martinez/entangled/subscription","commits_url":"https://api.github.com/repos/thibault-martinez/entangled/commits{/sha}","git_commits_url":"https://api.github.com/repos/thibault-martinez/entangled/git/commits{/sha}","comments_url":"https://api.github.com/repos/thibault-martinez/entangled/comments{/number}","issue_comment_url":"https://api.github.com/repos/thibault-martinez/entangled/issues/comments{/number}","contents_url":"https://api.github.com/repos/thibault-martinez/entangled/contents/{+path}","compare_url":"https://api.github.com/repos/thibault-martinez/entangled/compare/{base}...{head}","merges_url":"https://api.github.com/repos/thibault-martinez/entangled/merges","archive_url":"https://api.github.com/repos/thibault-martinez/entangled/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/thibault-martinez/entangled/downloads","issues_url":"https://api.github.com/repos/thibault-martinez/entangled/issues{/number}","pulls_url":"https://api.github.com/repos/thibault-martinez/entangled/pulls{/number}","milestones_url":"https://api.github.com/repos/thibault-martinez/entangled/milestones{/number}","notifications_url":"https://api.github.com/repos/thibault-martinez/entangled/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/thibault-martinez/entangled/labels{/name}","releases_url":"https://api.github.com/repos/thibault-martinez/entangled/releases{/id}","deployments_url":"https://api.github.com/repos/thibault-martinez/entangled/deployments","created_at":"2018-06-12T16:51:57Z","updated_at":"2018-11-08T08:08:37Z","pushed_at":"2018-11-08T11:53:24Z","git_url":"git://github.com/thibault-martinez/entangled.git","ssh_url":"git@github.com:thibault-martinez/entangled.git","clone_url":"https://github.com/thibault-martinez/entangled.git","svn_url":"https://github.com/thibault-martinez/entangled","homepage":null,"size":2196,"stargazers_count":0,"watchers_count":0,"language":"C","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":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"iotaledger:develop","ref":"develop","sha":"b4a64e9f7db709c04294e966013da4fae213d237","user":{"login":"iotaledger","id":20126597,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIwMTI2NTk3","avatar_url":"https://avatars3.githubusercontent.com/u/20126597?v=4","gravatar_id":"","url":"https://api.github.com/users/iotaledger","html_url":"https://github.com/iotaledger","followers_url":"https://api.github.com/users/iotaledger/followers","following_url":"https://api.github.com/users/iotaledger/following{/other_user}","gists_url":"https://api.github.com/users/iotaledger/gists{/gist_id}","starred_url":"https://api.github.com/users/iotaledger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iotaledger/subscriptions","organizations_url":"https://api.github.com/users/iotaledger/orgs","repos_url":"https://api.github.com/users/iotaledger/repos","events_url":"https://api.github.com/users/iotaledger/events{/privacy}","received_events_url":"https://api.github.com/users/iotaledger/received_events","type":"Organization","site_admin":false},"repo":{"id":137051507,"node_id":"MDEwOlJlcG9zaXRvcnkxMzcwNTE1MDc=","name":"entangled","full_name":"iotaledger/entangled","private":false,"owner":{"login":"iotaledger","id":20126597,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIwMTI2NTk3","avatar_url":"https://avatars3.githubusercontent.com/u/20126597?v=4","gravatar_id":"","url":"https://api.github.com/users/iotaledger","html_url":"https://github.com/iotaledger","followers_url":"https://api.github.com/users/iotaledger/followers","following_url":"https://api.github.com/users/iotaledger/following{/other_user}","gists_url":"https://api.github.com/users/iotaledger/gists{/gist_id}","starred_url":"https://api.github.com/users/iotaledger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iotaledger/subscriptions","organizations_url":"https://api.github.com/users/iotaledger/orgs","repos_url":"https://api.github.com/users/iotaledger/repos","events_url":"https://api.github.com/users/iotaledger/events{/privacy}","received_events_url":"https://api.github.com/users/iotaledger/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/iotaledger/entangled","description":"enTangle'd is an amalgamation of all things Tangle","fork":false,"url":"https://api.github.com/repos/iotaledger/entangled","forks_url":"https://api.github.com/repos/iotaledger/entangled/forks","keys_url":"https://api.github.com/repos/iotaledger/entangled/keys{/key_id}","collaborators_url":"https://api.github.com/repos/iotaledger/entangled/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/iotaledger/entangled/teams","hooks_url":"https://api.github.com/repos/iotaledger/entangled/hooks","issue_events_url":"https://api.github.com/repos/iotaledger/entangled/issues/events{/number}","events_url":"https://api.github.com/repos/iotaledger/entangled/events","assignees_url":"https://api.github.com/repos/iotaledger/entangled/assignees{/user}","branches_url":"https://api.github.com/repos/iotaledger/entangled/branches{/branch}","tags_url":"https://api.github.com/repos/iotaledger/entangled/tags","blobs_url":"https://api.github.com/repos/iotaledger/entangled/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/iotaledger/entangled/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/iotaledger/entangled/git/refs{/sha}","trees_url":"https://api.github.com/repos/iotaledger/entangled/git/trees{/sha}","statuses_url":"https://api.github.com/repos/iotaledger/entangled/statuses/{sha}","languages_url":"https://api.github.com/repos/iotaledger/entangled/languages","stargazers_url":"https://api.github.com/repos/iotaledger/entangled/stargazers","contributors_url":"https://api.github.com/repos/iotaledger/entangled/contributors","subscribers_url":"https://api.github.com/repos/iotaledger/entangled/subscribers","subscription_url":"https://api.github.com/repos/iotaledger/entangled/subscription","commits_url":"https://api.github.com/repos/iotaledger/entangled/commits{/sha}","git_commits_url":"https://api.github.com/repos/iotaledger/entangled/git/commits{/sha}","comments_url":"https://api.github.com/repos/iotaledger/entangled/comments{/number}","issue_comment_url":"https://api.github.com/repos/iotaledger/entangled/issues/comments{/number}","contents_url":"https://api.github.com/repos/iotaledger/entangled/contents/{+path}","compare_url":"https://api.github.com/repos/iotaledger/entangled/compare/{base}...{head}","merges_url":"https://api.github.com/repos/iotaledger/entangled/merges","archive_url":"https://api.github.com/repos/iotaledger/entangled/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/iotaledger/entangled/downloads","issues_url":"https://api.github.com/repos/iotaledger/entangled/issues{/number}","pulls_url":"https://api.github.com/repos/iotaledger/entangled/pulls{/number}","milestones_url":"https://api.github.com/repos/iotaledger/entangled/milestones{/number}","notifications_url":"https://api.github.com/repos/iotaledger/entangled/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/iotaledger/entangled/labels{/name}","releases_url":"https://api.github.com/repos/iotaledger/entangled/releases{/id}","deployments_url":"https://api.github.com/repos/iotaledger/entangled/deployments","created_at":"2018-06-12T09:49:47Z","updated_at":"2018-11-08T09:42:10Z","pushed_at":"2018-11-08T12:11:19Z","git_url":"git://github.com/iotaledger/entangled.git","ssh_url":"git@github.com:iotaledger/entangled.git","clone_url":"https://github.com/iotaledger/entangled.git","svn_url":"https://github.com/iotaledger/entangled","homepage":"","size":1973,"stargazers_count":37,"watchers_count":37,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":33,"mirror_url":null,"archived":false,"open_issues_count":110,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":33,"open_issues":110,"watchers":37,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/iotaledger/entangled/pulls/484"},"html":{"href":"https://github.com/iotaledger/entangled/pull/484"},"issue":{"href":"https://api.github.com/repos/iotaledger/entangled/issues/484"},"comments":{"href":"https://api.github.com/repos/iotaledger/entangled/issues/484/comments"},"review_comments":{"href":"https://api.github.com/repos/iotaledger/entangled/pulls/484/comments"},"review_comment":{"href":"https://api.github.com/repos/iotaledger/entangled/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/iotaledger/entangled/pulls/484/commits"},"statuses":{"href":"https://api.github.com/repos/iotaledger/entangled/statuses/ec15c796b1cb3c08d3cefaf4bea6b3abf02b5646"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"th0br0"}}