All Downloads are FREE. Search and download functionalities are using the official Maven repository.

convex.api.ConvexLocal Maven / Gradle / Ivy

package convex.api;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;

import convex.core.Result;
import convex.core.State;
import convex.core.crypto.AKeyPair;
import convex.core.data.ACell;
import convex.core.data.Address;
import convex.core.data.Hash;
import convex.core.data.Ref;
import convex.core.data.SignedData;
import convex.core.data.Vectors;
import convex.core.data.prim.CVMLong;
import convex.core.exceptions.MissingDataException;
import convex.core.store.AStore;
import convex.core.transactions.ATransaction;
import convex.core.util.Utils;
import convex.net.MessageType;
import convex.net.message.MessageLocal;
import convex.peer.Server;

/**
 * Convex Client implementation supporting a direct connection to a Peer Server in the same JVM.
 */
public class ConvexLocal extends Convex {

	private final Server server;

	protected ConvexLocal(Server server, Address address, AKeyPair keyPair) {
		super(address, keyPair);
		this.server=server;
	}
	
	public static ConvexLocal create(Server server, Address address, AKeyPair keyPair) {
		return new ConvexLocal(server, address,keyPair);
	}

	@Override
	public boolean isConnected() {
		return server.isLive();
	}


	@Override
	public  CompletableFuture acquire(Hash hash, AStore store) {
		CompletableFuture f = new CompletableFuture();
		new Thread(new Runnable() {
			@SuppressWarnings("unchecked")
			@Override
			public void run() {
				AStore remoteStore=server.getStore();
				Ref ref=remoteStore.refForHash(hash);
				if (ref==null) {
					f.completeExceptionally(new MissingDataException(remoteStore,hash));
				} else {
					ref=store.storeTopRef(ref, Ref.PERSISTED, null);
					f.complete((T) ref.getValue());
				}
			}
		}).run();
		return f;
	}

	@Override
	public CompletableFuture requestStatus() {
		return makeMessageFuture(MessageType.STATUS,CVMLong.create(makeID()));
	}
	
	@Override
	public CompletableFuture transact(SignedData signed) {
		CompletableFuture r= makeMessageFuture(MessageType.TRANSACT,Vectors.of(makeID(),signed));
		maybeUpdateSequence(signed);
		return r;
	}


	@Override
	public CompletableFuture requestChallenge(SignedData data) {
		return makeMessageFuture(MessageType.CHALLENGE,data);
	}

	@Override
	public CompletableFuture query(ACell query, Address address) {
		return makeMessageFuture(MessageType.QUERY,Vectors.of(makeID(),query,address));
	}
	
	private long idCounter=0;
	
	private long makeID() {
		return idCounter++;
	}

	private CompletableFuture makeMessageFuture(MessageType type, ACell payload) {
		CompletableFuture cf=new CompletableFuture<>();
		Consumer resultHandler=makeResultHandler(cf);
		MessageLocal ml=MessageLocal.create(type,payload, server, resultHandler);
		try {
			server.queueMessage(ml);
		} catch (InterruptedException e) {
			cf.completeExceptionally(e);
		}
		return cf;
		
	}

	private Consumer makeResultHandler(CompletableFuture cf) {
		return r->{
			cf.complete(r);
		};
	}

	@Override
	public void close() {
		// Nothing to do
	}

	@Override
	public CompletableFuture acquireState() throws TimeoutException {
		return CompletableFuture.completedFuture(getState());
	}
	
	private State getState() {
		return server.getPeer().getConsensusState();
	}
	
	@Override
	public long getSequence() {
		if (sequence==null) {
			sequence=getState().getAccount(address).getSequence();
		}
		return sequence;
	}
	
	@Override
	public long getSequence(Address addr) {
		if (Utils.equals(address, addr)) return getSequence();
		return getState().getAccount(addr).getSequence();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy