package peergos.server.mutable; import peergos.shared.cbor.*; import peergos.shared.crypto.asymmetric.*; import peergos.shared.merklebtree.*; import peergos.shared.mutable.*; import peergos.shared.storage.ContentAddressedStorage; import java.util.concurrent.*; public class PinningMutablePointers implements MutablePointers { private static final boolean LOGGING = true; private final MutablePointers target; private final ContentAddressedStorage storage; public PinningMutablePointers(MutablePointers target, ContentAddressedStorage storage) { this.target = target; this.storage = storage; } @Override public CompletableFuture<Boolean> setPointer(PublicSigningKey owner, PublicSigningKey signer, byte[] sharingKeySignedBtreeRootHashes) { // first pin new root byte[] message = signer.unsignMessage(sharingKeySignedBtreeRootHashes); HashCasPair cas = HashCasPair.fromCbor(CborObject.fromByteArray(message)); long t1 = System.currentTimeMillis(); return storage.recursivePin(cas.updated.get()).thenCompose(pins -> { if (!pins.contains(cas.updated.get())) { CompletableFuture<Boolean> err = new CompletableFuture<>(); err.completeExceptionally(new IllegalStateException("Couldn't pin new hash: " + cas.updated.get())); return err; } long t2 = System.currentTimeMillis(); if (LOGGING) System.out.println("Pinning "+cas.updated+" took: " + (t2 -t1) + " mS"); return target.setPointer(owner, signer, sharingKeySignedBtreeRootHashes) .thenCompose(b -> { if (!b) { CompletableFuture<Boolean> err = new CompletableFuture<>(); err.completeExceptionally(new IllegalStateException("Couldn't update mutable pointer, cas failed: " + cas)); return err; } long t3 = System.currentTimeMillis(); // unpin old root return !cas.original.isPresent() ? CompletableFuture.completedFuture(true) : storage.recursiveUnpin(cas.original.get()) .thenApply(unpins -> { long t4 = System.currentTimeMillis(); if (LOGGING) System.out.println("Unpinning "+cas.original+" took: " + (t4 -t3) + " mS"); return unpins.contains(cas.original.get()); }); }); }); } @Override public CompletableFuture<MaybeMultihash> getPointer(PublicSigningKey encodedSharingKey) { return target.getPointer(encodedSharingKey); } }