Skip to content

Commit

Permalink
Merge pull request #87 from Peergos/feat/new-api-calls
Browse files Browse the repository at this point in the history
Add new API calls for getting ipns records, and bulk block deletion
  • Loading branch information
ianopolous authored Mar 22, 2024
2 parents e7452b8 + 0834816 commit 50c8fd0
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.peergos</groupId>
<artifactId>nabu</artifactId>
<version>v0.7.4</version>
<version>v0.7.5</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/peergos/AggregatedMetrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ private static Counter build(String name, String help) {
public static final Counter API_BLOCK_GET = build("api_block_get", "Total calls to block/get.");
public static final Counter API_BLOCK_PUT = build("api_block_put", "Total calls to block/put.");
public static final Counter API_BLOCK_RM = build("api_block_rm", "Total calls to block/rm.");
public static final Counter API_BLOCK_RM_BULK = build("api_block_rm_bulk", "Total calls to block/rm/bulk.");
public static final Counter API_BLOCK_STAT = build("api_block_stat", "Total calls to block/stat.");
public static final Counter API_REFS_LOCAL = build("api_refs_local", "Total calls to refs/local.");
public static final Counter API_BLOCK_HAS = build("api_block_has", "Total calls to block/has.");
public static final Counter API_BLOOM_ADD = build("api_bloom_add", "Total calls to bloom/add.");
public static final Counter API_FIND_PROVS = build("api_dht_findprovs", "Total calls to dht/findprovs.");
public static final Counter API_IPNS_GET = build("api_ipns_get", "Total calls to ipns/get.");

public static void startExporter(String address, int port) throws IOException {
LOG.info("Starting metrics server at " + address + ":" + port);
Expand Down
71 changes: 69 additions & 2 deletions src/main/java/org/peergos/net/APIHandler.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package org.peergos.net;

import io.ipfs.cid.Cid;
import io.ipfs.multihash.*;
import io.libp2p.core.PeerId;
import io.libp2p.crypto.keys.*;
import org.peergos.*;
import org.peergos.protocol.ipns.*;
import org.peergos.protocol.ipns.pb.*;
import org.peergos.util.*;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;
import java.io.*;
import java.nio.*;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.*;

public class APIHandler extends Handler {
public static final String API_URL = "/api/v0/";
public static final Version CURRENT_VERSION = Version.parse("0.7.2");
public static final Version CURRENT_VERSION = Version.parse("0.7.5");
private static final Logger LOG = Logging.LOG();

private static final boolean LOGGING = true;
Expand All @@ -23,12 +28,14 @@ public class APIHandler extends Handler {
public static final String GET = "block/get";
public static final String PUT = "block/put";
public static final String RM = "block/rm";
public static final String RM_BULK = "block/rm/bulk";
public static final String STAT = "block/stat";
public static final String REFS_LOCAL = "refs/local";
public static final String BLOOM_ADD = "bloom/add";
public static final String HAS = "block/has";

public static final String FIND_PROVS = "dht/findprovs";
public static final String IPNS_GET = "ipns/get";

private final EmbeddedIpfs ipfs;
private final int maxBlockSize;
Expand Down Expand Up @@ -141,6 +148,31 @@ public void handleCallToAPI(HttpExchange httpExchange) {
}
break;
}
case RM_BULK: {
AggregatedMetrics.API_BLOCK_RM_BULK.inc();
Map<String, Object> json = (Map<String, Object>) JSONParser.parse(new String(readFully(httpExchange.getRequestBody())));
List<Cid> cids = ((List<String>)json.get("cids"))
.stream()
.map(Cid::decode)
.collect(Collectors.toList());
boolean deleted = true;
for (Cid cid : cids) {
deleted &= ipfs.blockstore.rm(cid).join();
}

if (deleted) {
Map res = new HashMap<>();
res.put("Res", "true");
replyJson(httpExchange, JSONParser.toString(res));
} else {
try {
httpExchange.sendResponseHeaders(400, 0);
} catch (IOException ioe) {
HttpUtil.replyError(httpExchange, ioe);
}
}
break;
}
case STAT: { // https://docs.ipfs.tech/reference/kubo/rpc/#api-v0-block-stat
AggregatedMetrics.API_BLOCK_STAT.inc();
if (args == null || args.size() != 1) {
Expand Down Expand Up @@ -217,6 +249,31 @@ public void handleCallToAPI(HttpExchange httpExchange) {
replyBytes(httpExchange, sb.toString().getBytes());
break;
}
case IPNS_GET: {
AggregatedMetrics.API_IPNS_GET.inc();
if (args == null || args.size() != 1) {
throw new APIException("argument \"signer\" is required");
}
Multihash signer = Multihash.fromBase58(args.get(0));
if (signer.getType() != Multihash.Type.id)
throw new IllegalStateException("Can only resolve Ed25519 ipns mappings");
byte[] pubKeymaterial = Arrays.copyOfRange(signer.getHash(), 4, 36);
io.libp2p.core.crypto.PubKey pub = new Ed25519PublicKey(new org.bouncycastle.crypto.params.Ed25519PublicKeyParameters(pubKeymaterial, 0));
List<IpnsRecord> records = ipfs.resolveRecords(pub, 1)
.stream()
.sorted()
.collect(Collectors.toList());
if (records.isEmpty())
throw new IllegalStateException("Couldn't resolve " + signer);
IpnsRecord latest = records.get(records.size() - 1);
Ipns.IpnsEntry entry = Ipns.IpnsEntry.parseFrom(ByteBuffer.wrap(latest.raw));
Map<String, Object> res = new HashMap<>();
res.put("sig", ArrayOps.bytesToHex(entry.getSignatureV2().toByteArray()));
res.put("data", ArrayOps.bytesToHex(entry.getData().toByteArray()));
String json = JSONParser.toString(res);
replyJson(httpExchange, json);
break;
}
default: {
httpExchange.sendResponseHeaders(404, 0);
break;
Expand All @@ -231,4 +288,14 @@ public void handleCallToAPI(HttpExchange httpExchange) {
LOG.info("API Handler handled " + path + " query in: " + (t2 - t1) + " mS");
}
}

private byte[] readFully(InputStream in) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] b = new byte[0x1000];
int nRead;
while ((nRead = in.read(b, 0, b.length)) != -1 )
bout.write(b, 0, nRead);
in.close();
return bout.toByteArray();
}
}

0 comments on commit 50c8fd0

Please sign in to comment.