- Generalizing OTS Calendar access

- Developing OTS access points with OkHttp
This commit is contained in:
Vitor Pamplona
2024-02-25 17:04:51 -05:00
parent 880915e702
commit 6a7d33e58f
15 changed files with 498 additions and 32 deletions

View File

@@ -25,6 +25,7 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.hexToByteArray
import com.vitorpamplona.quartz.ots.BlockstreamExplorer
import com.vitorpamplona.quartz.ots.CalendarPureJavaBuilder
import com.vitorpamplona.quartz.ots.DetachedTimestampFile
import com.vitorpamplona.quartz.ots.Hash
import com.vitorpamplona.quartz.ots.OpenTimestamps
@@ -58,7 +59,7 @@ class OtsEvent(
val detachedOts = DetachedTimestampFile.deserialize(otsByteArray())
val result = OpenTimestamps(BlockstreamExplorer()).verify(detachedOts, digest)
val result = otsInstance.verify(detachedOts, digest)
if (result == null || result.isEmpty()) {
return null
} else {
@@ -73,17 +74,19 @@ class OtsEvent(
fun info(): String {
val detachedOts = DetachedTimestampFile.deserialize(otsByteArray())
return OpenTimestamps(BlockstreamExplorer()).info(detachedOts)
return otsInstance.info(detachedOts)
}
companion object {
const val KIND = 1040
const val ALT = "Opentimestamps Attestation"
var otsInstance = OpenTimestamps(BlockstreamExplorer(), CalendarPureJavaBuilder())
fun stamp(eventId: HexKey): ByteArray {
val hash = Hash(eventId.hexToByteArray(), OpSHA256._TAG)
val file = DetachedTimestampFile.from(hash)
val timestamp = OpenTimestamps(BlockstreamExplorer()).stamp(file)
val timestamp = otsInstance.stamp(file)
val detachedToSerialize = DetachedTimestampFile(hash.getOp(), timestamp)
return detachedToSerialize.serialize()
}

View File

@@ -14,7 +14,7 @@ import java.util.Map;
/**
* Class representing remote calendar server interface.
*/
public class Calendar {
public class Calendar implements ICalendar {
private String url;
@@ -46,6 +46,7 @@ public class Calendar {
* @throws UrlException if url is not reachable.
* @throws DeserializationException if the data is corrupt
*/
@Override
public Timestamp submit(byte[] digest)
throws ExceededSizeException, UrlException, DeserializationException {
try {
@@ -85,6 +86,7 @@ public class Calendar {
* @throws CommitmentNotFoundException if commit is not found.
* @throws DeserializationException if the data is corrupt
*/
@Override
public Timestamp getTimestamp(byte[] commitment) throws DeserializationException, ExceededSizeException, CommitmentNotFoundException, UrlException {
try {
Map<String, String> headers = new HashMap<>();

View File

@@ -10,12 +10,11 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
/**
* For making async calls to a calendar server
*/
public class CalendarAsyncSubmit implements Callable<Optional<Timestamp>> {
public class CalendarAsyncSubmit implements ICalendarAsyncSubmit {
private String url;
private byte[] digest;

View File

@@ -0,0 +1,6 @@
package com.vitorpamplona.quartz.ots;
public interface CalendarBuilder {
public ICalendar newSyncCalendar(String url);
public ICalendarAsyncSubmit newAsyncCalendar(String url, byte[] digest);
}

View File

@@ -0,0 +1,10 @@
package com.vitorpamplona.quartz.ots;
public class CalendarPureJavaBuilder implements CalendarBuilder {
public ICalendar newSyncCalendar(String url) {
return new Calendar(url);
}
public ICalendarAsyncSubmit newAsyncCalendar(String url, byte[] digest) {
return new CalendarAsyncSubmit(url, digest);
}
}

View File

@@ -0,0 +1,13 @@
package com.vitorpamplona.quartz.ots;
import com.vitorpamplona.quartz.ots.exceptions.CommitmentNotFoundException;
import com.vitorpamplona.quartz.ots.exceptions.DeserializationException;
import com.vitorpamplona.quartz.ots.exceptions.ExceededSizeException;
import com.vitorpamplona.quartz.ots.exceptions.UrlException;
public interface ICalendar {
Timestamp submit(byte[] digest)
throws ExceededSizeException, UrlException, DeserializationException;
Timestamp getTimestamp(byte[] commitment) throws DeserializationException, ExceededSizeException, CommitmentNotFoundException, UrlException;
}

View File

@@ -0,0 +1,9 @@
package com.vitorpamplona.quartz.ots;
import java.util.Optional;
import java.util.concurrent.Callable;
public interface ICalendarAsyncSubmit extends Callable<Optional<Timestamp>> {
@Override
Optional<Timestamp> call() throws Exception;
}

View File

@@ -33,9 +33,12 @@ import java.util.concurrent.Executors;
public class OpenTimestamps {
BitcoinExplorer explorer;
CalendarBuilder calBuilder;
public OpenTimestamps(BitcoinExplorer explorer) {
public OpenTimestamps(BitcoinExplorer explorer, CalendarBuilder builder) {
this.explorer = explorer;
this.calBuilder = builder;
}
/**

View File

@@ -91,29 +91,4 @@ public class Request implements Callable<Response> {
return response;
}
public static String urlEncodeUTF8(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
public static String urlEncodeUTF8(Map<?, ?> map) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(String.format("%s=%s",
urlEncodeUTF8(entry.getKey().toString()),
urlEncodeUTF8(entry.getValue().toString())
));
}
return sb.toString();
}
}