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.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;

import convex.core.Result;
import convex.core.State;
import convex.core.crypto.AKeyPair;
import convex.core.data.ACell;
import convex.core.data.AccountStatus;
import convex.core.data.Address;
import convex.core.data.Cells;
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.ThreadUtils;
import convex.net.Message;
import convex.net.MessageType;
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;
		this.preCompile=true; // pre-compile by default if local peer
	}
	
	public static ConvexLocal create(Server server, Address address, AKeyPair keyPair) {
		return new ConvexLocal(server, address,keyPair);
	}

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

	@SuppressWarnings("unchecked")
	@Override
	public  CompletableFuture acquire(Hash hash, AStore store) {
		CompletableFuture f = new CompletableFuture();
		ThreadUtils.runVirtual(()-> {
			AStore peerStore=server.getStore();
			Ref ref=peerStore.refForHash(hash);
			if (ref==null) {
				f.completeExceptionally(new MissingDataException(peerStore,hash));
			} else {
				try {
					ref=store.storeTopRef(ref, Ref.PERSISTED, null);
				} catch (IOException e) {
					f.completeExceptionally(e);
				}
				f.complete((T) ref.getValue());
			}
		});
		return f;
	}

	@Override
	public CompletableFuture requestStatus() {
		return makeMessageFuture(MessageType.STATUS,CVMLong.create(makeID()));
	}
	
	@Override
	public CompletableFuture transact(SignedData signed) {
		maybeUpdateSequence(signed);
		CompletableFuture r= makeMessageFuture(MessageType.TRANSACT,Vectors.of(makeID(),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<>();
		Predicate resultHandler=makeResultHandler(cf);
		Message ml=Message.create(type,payload, resultHandler);
		server.getReceiveAction().accept(ml);
		return cf;
	}

	private Predicate makeResultHandler(CompletableFuture cf) {
		return m->{
			Result r=m.toResult();
			if (r.getErrorCode()!=null) {
				sequence=null;
			}
			cf.complete(r);
			return true;
		};
	}

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

	@Override
	public CompletableFuture acquireState() {
		return CompletableFuture.completedFuture(getState());
	}
	
	public State getState() {
		return server.getPeer().getConsensusState();
	}
	
	@Override
	public Server getLocalServer() {
		return server;
	}
	
	@Override
	public long getSequence() {
		if (sequence==null) {
			AccountStatus as=getState().getAccount(address);
			if (as==null) return 0;
			sequence=as.getSequence();
		}
		return sequence;
	}
	
	@Override
	public long getSequence(Address addr) {
		if (Cells.equals(address, addr)) return getSequence();
		return getState().getAccount(addr).getSequence();
	}

	@Override
	public String toString() {
		return "Local Convex instance on "+server.getHostAddress();
	}

	@Override
	public InetSocketAddress getHostAddress() {
		return server.getHostAddress();
	}

	@Override
	public Long getBalance() {
		return server.getPeer().getConsensusState().getBalance(address);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy