package peergos.server.storage;
import peergos.shared.cbor.*;
import peergos.shared.crypto.asymmetric.*;
import peergos.shared.io.ipfs.multihash.*;
import peergos.shared.io.ipfs.cid.*;
import peergos.shared.storage.ContentAddressedStorage;
import java.security.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
public class RAMStorage implements ContentAddressedStorage {
private static final int CID_V1 = 1;
private Map<Multihash, byte[]> storage = new HashMap<>();
private final Set<Multihash> pinnedRoots = new HashSet<>();
@Override
public CompletableFuture<List<Multihash>> put(PublicSigningKey writer, List<byte[]> blocks) {
return CompletableFuture.completedFuture(blocks.stream()
.map(b -> {
Cid cid = hashToCid(b);
put(cid, b);
return cid;
}).collect(Collectors.toList()));
}
private synchronized void put(Cid cid, byte[] data) {
storage.put(cid, data);
}
@Override
public CompletableFuture<Optional<CborObject>> get(Multihash object) {
return CompletableFuture.completedFuture(Optional.of(getAndParseObject(object)));
}
private synchronized CborObject getAndParseObject(Multihash hash) {
if (!storage.containsKey(hash))
throw new IllegalStateException("Hash not present! "+ hash);
return CborObject.fromByteArray(storage.get(hash));
}
public synchronized void clear() {
storage.clear();
}
public synchronized int size() {
return storage.size();
}
@Override
public CompletableFuture<List<Multihash>> recursivePin(Multihash h) {
return CompletableFuture.completedFuture(Arrays.asList(h));
}
@Override
public CompletableFuture<List<Multihash>> recursiveUnpin(Multihash h) {
return CompletableFuture.completedFuture(Arrays.asList(h));
}
@Override
public CompletableFuture<List<Multihash>> getLinks(Multihash root) {
return get(root).thenApply(opt -> opt
.map(cbor -> cbor.links())
.orElse(Collections.emptyList())
);
}
@Override
public CompletableFuture<Optional<Integer>> getSize(Multihash block) {
if (!storage.containsKey(block))
return CompletableFuture.completedFuture(Optional.empty());
return CompletableFuture.completedFuture(Optional.of(storage.get(block).length));
}
public static Cid hashToCid(byte[] input) {
byte[] hash = hash(input);
Multihash multihash = new Multihash(Multihash.Type.sha2_256, hash);
return new Cid(CID_V1, Cid.Codec.DagCbor, multihash);
}
public static byte[] hash(byte[] input)
{
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(input);
return md.digest();
} catch (NoSuchAlgorithmException e)
{
throw new IllegalStateException("couldn't find hash algorithm");
}
}
}