Skip to content

Commit f21eb6c

Browse files
committed
Support Reader tag #Signed for SignedData
1 parent 84a2747 commit f21eb6c

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

convex-core/src/main/java/convex/core/data/Cells.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -264,18 +264,25 @@ public static <T extends ACell> T intern(T value) {
264264

265265
@SuppressWarnings("unchecked")
266266
public static ACell createTagged(Symbol sym, ACell value) throws ParseException {
267-
268267
switch (sym.getName().toString()) {
269-
case "Index":
270-
if (!(value instanceof AHashMap)) throw new ParseException(sym+" tag must be on a map");
271-
Index<ABlobLike<?>,ACell> index= Index.create((AHashMap<ABlobLike<?>,ACell>)value);
272-
if (index==null) throw new ParseException("Invalid #Index keys");
273-
return index;
274-
case "Result":
275-
if (!(value instanceof AHashMap)) throw new ParseException(sym+" tag must be on a map");
276-
Result r= Result.fromData((AHashMap<ABlobLike<?>,ACell>)value);
277-
if (r==null) throw new ParseException("Invalid #Result keys");
278-
return r;
268+
case "Index": {
269+
if (!(value instanceof AHashMap)) throw new ParseException(sym+" tag must be on a map");
270+
Index<ABlobLike<?>,ACell> index= Index.create((AHashMap<ABlobLike<?>,ACell>)value);
271+
if (index==null) throw new ParseException("Invalid #Index keys");
272+
return index;
273+
}
274+
case "Result": {
275+
if (!(value instanceof AHashMap)) throw new ParseException(sym+" tag must be on a map");
276+
Result r= Result.fromData((AHashMap<ABlobLike<?>,ACell>)value);
277+
if (r==null) throw new ParseException("Invalid #Result keys");
278+
return r;
279+
}
280+
case "Signed": {
281+
if (!(value instanceof AHashMap)) throw new ParseException(sym+" tag must be on a map");
282+
SignedData<?> r= SignedData.fromData((AHashMap<Keyword,ACell>)value);
283+
if (r==null) throw new ParseException("Invalid #Signed keys");
284+
return r;
285+
}
279286
}
280287
return value;
281288
}

convex-core/src/main/java/convex/core/data/SignedData.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import convex.core.crypto.ASignature;
55
import convex.core.crypto.Ed25519Signature;
66
import convex.core.crypto.Providers;
7+
import convex.core.data.util.BlobBuilder;
78
import convex.core.exceptions.BadFormatException;
89
import convex.core.exceptions.BadSignatureException;
910
import convex.core.exceptions.InvalidDataException;
11+
import convex.core.lang.RT;
1012
import convex.core.lang.RecordFormat;
1113

1214
/**
@@ -50,6 +52,7 @@ public final class SignedData<T extends ACell> extends ARecord {
5052
private static final Keyword[] KEYS = new Keyword[] { Keywords.PUBLIC_KEY, Keywords.SIGNATURE, Keywords.VALUE };
5153

5254
private static final RecordFormat FORMAT = RecordFormat.of(KEYS);
55+
private static final StringShort SIGNED_TAG = StringShort.create("#Signed");
5356

5457
//Cached fields
5558
private AccountKey verifiedKey=null;
@@ -196,6 +199,14 @@ public int encodeRaw(byte[] bs, int pos) {
196199
pos = valueRef.encode(bs,pos);
197200
return pos;
198201
}
202+
203+
@Override
204+
public boolean print(BlobBuilder sb, long limit) {
205+
sb.append(SIGNED_TAG);
206+
sb.append(' ');
207+
return super.print(sb,limit);
208+
}
209+
199210

200211
@Override
201212
public int estimatedEncodingSize() {
@@ -390,4 +401,12 @@ public boolean equals(ACell o) {
390401
return valueRef.equals(b.valueRef);
391402
}
392403

404+
@SuppressWarnings("unchecked")
405+
public static <T extends ACell> SignedData<T> fromData(AHashMap<Keyword, ACell> value) {
406+
Ref<T> ref=Ref.get((T)(value.get(Keywords.VALUE)));
407+
AccountKey key=AccountKey.parse(value.get(Keywords.PUBLIC_KEY));
408+
ASignature sig=ASignature.fromBlob(RT.ensureBlob(value.get(Keywords.SIGNATURE)));
409+
return create(key,sig,ref);
410+
}
411+
393412
}

convex-core/src/test/java/convex/core/lang/ReaderTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ public void testMetadata() {
360360
doIdempotencyTest(CVMBool.TRUE);
361361
doIdempotencyTest(Samples.LONG_MAP_10);
362362
doIdempotencyTest(Samples.BAD_HASH);
363+
doIdempotencyTest(Samples.INT_INDEX_7);
363364
doIdempotencyTest(Reader.readAll("(def ^{:foo 2} a 1)"));
364365
doIdempotencyTest(Reader.readAll("(fn ^{:foo 2} [] bar/baz)"));
365366
}
@@ -397,6 +398,7 @@ public void doIdempotencyTest(ACell cell) {
397398
doReadPrintTest("\"[\""); // string containing a single square bracket should be OK
398399
doReadPrintTest("1.0");
399400
doReadPrintTest("[:foo bar]");
401+
doReadPrintTest("#Index {}");
400402
doReadPrintTest("^{} 0xa89e59cc8ab9fc6a13785a37938c85b306b24663415effc01063a6e25ef52ebcd3647d3a77e0a33908a372146fdccab6");
401403
}
402404

convex-peer/src/main/java/convex/api/Convex.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,18 @@ public final synchronized CompletableFuture<Result> transact(ATransaction transa
408408
* @return Signed transaction ready to submit
409409
* @throws ResultException If an error occurs preparing the transaction (e.g. failure to pre-compile)
410410
*/
411+
@SuppressWarnings("unchecked")
411412
public SignedData<ATransaction> prepareTransaction(ACell code) throws ResultException,InterruptedException {
412413
ATransaction transaction;
413414
if (code instanceof ATransaction) {
414415
transaction=(ATransaction)code;
415-
} else if (code instanceof SignedData) {
416-
throw new IllegalArgumentException("Can't prepare transaction that is already signed");
417416
} else {
417+
if (code instanceof SignedData) {
418+
SignedData<?> signed=(SignedData<?>) code;
419+
ACell val=signed.getValue();
420+
if (val instanceof ATransaction) return (SignedData<ATransaction>) signed;
421+
code=val;
422+
}
418423
if (isPreCompile() ) {
419424
Result compResult=preCompile(code).join();
420425
if (compResult.isError()) throw new ResultException(compResult);

0 commit comments

Comments
 (0)