Skip to content

Commit 8e82fb1

Browse files
committed
Result handling updates to give :source
1 parent 6b31a6a commit 8e82fb1

File tree

8 files changed

+66
-10
lines changed

8 files changed

+66
-10
lines changed

convex-core/src/main/java/convex/core/Result.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ public static Result fromContext(CVMLong id,ResultContext rc) {
322322
if (rc.memUsed>0) info=info.assoc(Keywords.MEM, CVMLong.create(rc.memUsed));
323323
if (rc.totalFees>0) info=info.assoc(Keywords.FEES, CVMLong.create(rc.totalFees));
324324
if (rc.juiceUsed>0) info=info.assoc(Keywords.JUICE, CVMLong.create(rc.juiceUsed));
325+
if (rc.source!=null) info=info.assoc(Keywords.SOURCE, rc.source);
325326

326327
return create(id,(ACell)result,errorCode,info);
327328
}
@@ -346,6 +347,7 @@ public Result withExtraInfo(Map<Keyword,ACell> extInfo) {
346347
*/
347348
public static Result fromContext(Context ctx) {
348349
ACell rval=(ctx.isExceptional())?ctx.getExceptional().getMessage():ctx.getResult();
350+
349351
return create(null,rval,ctx.getErrorCode(),null);
350352
}
351353

@@ -398,7 +400,7 @@ public static Result fromException(Throwable e) {
398400
private static final Result INTERRUPTED_RESULT=Result.error(ErrorCodes.INTERRUPTED,Strings.create("Interrupted!"));
399401

400402
/**
401-
* Returns a Result representing a thread interrup, AND sets the interrupt status on the current thread
403+
* Returns a Result representing a thread interrupt, AND sets the interrupt status on the current thread
402404
* @return
403405
*/
404406
public static Result interruptThread() {

convex-core/src/main/java/convex/core/ResultContext.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import convex.core.transactions.ATransaction;
99

1010
/**
11-
* Class for preparation of transaction results
11+
* Class for preparation of transaction results from the CVM
1212
*
1313
* Mutable so that results can be accumulated efficiently as processing proceeds
1414
*/
@@ -20,6 +20,7 @@ public class ResultContext {
2020
public Context context=null;
2121
public long totalFees=0;
2222
public long juiceUsed=0;
23+
public Keyword source=null;
2324

2425
public ResultContext(ATransaction transaction, long juicePrice) {
2526
this.juicePrice=juicePrice;
@@ -85,4 +86,13 @@ public boolean isError() {
8586
return context.isError();
8687
}
8788

89+
public ResultContext withSource(Keyword sourceCode) {
90+
this.source=sourceCode;
91+
return this;
92+
}
93+
94+
public Keyword getSource() {
95+
return source;
96+
}
97+
8898
}

convex-core/src/main/java/convex/core/State.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -511,21 +511,29 @@ public ResultContext applyTransaction(SignedData<? extends ATransaction> signedT
511511
Address addr=t.getOrigin();
512512
AccountStatus as = getAccount(addr);
513513
if (as==null) {
514-
return ResultContext.error(this,ErrorCodes.NOBODY,"Transaction for non-existent Account: "+addr);
514+
ResultContext rc=ResultContext.error(this,ErrorCodes.NOBODY,"Transaction for non-existent Account: "+addr);
515+
return rc.withSource(SourceCodes.CVM);
515516
} else {
516517

517518
// Update sequence number for target account
518519
long sequence=t.getSequence();
519520
long expectedSequence=as.getSequence()+1;
520521
if (sequence!=expectedSequence) {
521-
return ResultContext.error(this,ErrorCodes.SEQUENCE, "Sequence = "+sequence+" but expected "+expectedSequence);
522+
ResultContext rc=ResultContext.error(this,ErrorCodes.SEQUENCE, "Sequence = "+sequence+" but expected "+expectedSequence);
523+
return rc.withSource(SourceCodes.CVM);
522524
}
523525

524526
AccountKey key=as.getAccountKey();
525-
if (key==null) return ResultContext.error(this,ErrorCodes.STATE,"Transaction for account that is an Actor: "+addr);
527+
if (key==null) {
528+
ResultContext rc= ResultContext.error(this,ErrorCodes.STATE,"Transaction for account that is an Actor: "+addr);
529+
return rc.withSource(SourceCodes.CVM);
530+
}
526531

527532
boolean sigValid=signedTransaction.checkSignature(key);
528-
if (!sigValid) return ResultContext.error(this,ErrorCodes.SIGNATURE, Strings.BAD_SIGNATURE);
533+
if (!sigValid) {
534+
ResultContext rc= ResultContext.error(this,ErrorCodes.SIGNATURE, Strings.BAD_SIGNATURE);
535+
return rc.withSource(SourceCodes.CVM);
536+
}
529537
}
530538

531539
ResultContext ctx=applyTransaction(t);
@@ -575,6 +583,7 @@ public ResultContext applyTransaction(ATransaction t) {
575583
// - Non-existent Origin account
576584
// - Bad sequence number
577585
// Return context with no change, i.e. before executing the transaction
586+
rc.source=SourceCodes.CVM;
578587
}
579588

580589
return rc.withContext(ctx);

convex-core/src/main/java/convex/core/lang/Context.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import convex.core.Constants;
55
import convex.core.ErrorCodes;
66
import convex.core.ResultContext;
7+
import convex.core.SourceCodes;
78
import convex.core.State;
89
import convex.core.data.ACell;
910
import convex.core.data.AHashMap;
@@ -352,6 +353,7 @@ public Context completeTransaction(State initialState, ResultContext rc) {
352353
// consume whole balance
353354
juiceFees=balance;
354355
} else if (!rc.context.isExceptional()) {
356+
// Transaction appears to have succeeded, and will do unless memory accounting fails
355357
// do memory accounting as long as we didn't fail for any other reason
356358
// compute memory delta (memUsed) and store in ResultContext
357359
long memUsed=state.getMemorySize()-initialState.getMemorySize();
@@ -389,6 +391,9 @@ public Context completeTransaction(State initialState, ResultContext rc) {
389391
long allowanceCredit=-memUsed;
390392
account=account.withMemory(allowance+allowanceCredit);
391393
}
394+
} else {
395+
// Transaction failed in user code
396+
rc.source=SourceCodes.CODE;
392397
}
393398

394399
// Compute total fees
@@ -413,8 +418,10 @@ public Context completeTransaction(State initialState, ResultContext rc) {
413418
Context rctx=this.withState(state);
414419
if (juiceFailure) {
415420
rctx=rctx.withError(ErrorCodes.JUICE, "Insuffienct balance to cover juice fees of "+rc.getJuiceFees());
421+
rc.source=SourceCodes.CVM;
416422
} else if (memoryFailure) {
417423
rctx=rctx.withError(ErrorCodes.MEMORY, "Unable to allocate additional memory required for transaction ("+rc.memUsed+" bytes)");
424+
rc.source=SourceCodes.CVM;
418425
}
419426
return rctx;
420427
}

convex-core/src/test/java/convex/core/TransactionTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ public void testBadSequence() throws BadSignatureException {
238238
Context ctx=rc.context;
239239
assertEquals(ErrorCodes.SEQUENCE,ctx.getError().getCode());
240240

241+
// check source correctly identified
242+
assertEquals(SourceCodes.CVM, rc.source);
243+
244+
241245
// Sequence number in state should be unchanged
242246
assertEquals(0L,ctx.getAccountStatus(HERO).getSequence());
243247

@@ -285,6 +289,18 @@ private void checkNoTransactionEffects(State s, ResultContext rc) {
285289

286290
assertEquals(0,ctx.getJuiceUsed());
287291
}
292+
293+
@Test
294+
public void testJuiceFail() {
295+
State s=state();
296+
AccountStatus as=s.getAccount(HERO);
297+
long SEQ=as.getSequence()+1;
298+
ResultContext rc=s.applyTransaction(HERO_KP.signData(Invoke.create(HERO, SEQ,"(loop [] (def a 2) (recur))")));
299+
assertEquals(ErrorCodes.JUICE,rc.getErrorCode());
300+
assertEquals(SourceCodes.CVM,rc.getSource());
301+
checkNoTransactionEffects(s,rc);
302+
303+
}
288304

289305
@Test public void testBigValues() {
290306
// Checks in case there are oddities with big values / VLC encoding

convex-peer/src/main/java/convex/peer/QueryHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import convex.core.Result;
1010
import convex.core.ResultContext;
11+
import convex.core.SourceCodes;
1112
import convex.core.data.ACell;
1213
import convex.core.data.AVector;
1314
import convex.core.data.Address;
@@ -78,7 +79,7 @@ private void handleQuery(Message m) {
7879
ResultContext resultContext = server.getPeer().executeQuery(form, address);
7980

8081
// Report result back to message sender
81-
boolean resultReturned= m.returnResult(Result.fromContext(id, resultContext));
82+
boolean resultReturned= m.returnResult(Result.fromContext(id, resultContext).withSource(SourceCodes.PEER));
8283

8384
if (!resultReturned) {
8485
log.warn("Failed to send query result back to client with ID: {}", id);

convex-peer/src/main/java/convex/peer/TransactionHandler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import convex.core.ErrorCodes;
1818
import convex.core.Peer;
1919
import convex.core.Result;
20+
import convex.core.SourceCodes;
2021
import convex.core.State;
2122
import convex.core.data.ACell;
2223
import convex.core.data.AString;
@@ -117,7 +118,7 @@ protected void processMessage(Message m) {
117118
// Check our transaction is valid and we want to process it
118119
Result error=checkTransaction(sd);
119120
if (error!=null) {
120-
m.returnResult(error);
121+
m.returnResult(error.withSource(SourceCodes.PEER));
121122
return;
122123
}
123124

@@ -173,8 +174,7 @@ private Result checkTransaction(SignedData<ATransaction> sd) {
173174
return Result.error(ErrorCodes.SIGNATURE, Strings.BAD_SIGNATURE);
174175
}
175176
} catch (Exception e) {
176-
log.warn("Unexpected exception while checking transaction",e);
177-
return Result.error(ErrorCodes.UNEXPECTED, Strings.BAD_SIGNATURE);
177+
return Result.fromException(e);
178178
}
179179
// All checks passed OK!
180180
return null;

convex-peer/src/test/java/convex/api/ConvexRemoteTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import convex.core.ErrorCodes;
2020
import convex.core.Result;
21+
import convex.core.SourceCodes;
2122
import convex.core.crypto.AKeyPair;
2223
import convex.core.crypto.Ed25519Signature;
2324
import convex.core.data.Address;
@@ -107,6 +108,16 @@ public void testBadSignature() throws IOException, TimeoutException, Interrupted
107108
}
108109
}
109110

111+
@Test
112+
public void testNobody() throws IOException, TimeoutException, InterruptedException, ExecutionException {
113+
synchronized (network.SERVER) {
114+
Convex convex = Convex.connect(network.SERVER.getHostAddress(), Address.create(666666), KEYPAIR);
115+
Result r = convex.transact(CVMLong.ONE).get();
116+
assertEquals(ErrorCodes.NOBODY, r.getErrorCode());
117+
assertEquals(SourceCodes.PEER, r.getSource());
118+
}
119+
}
120+
110121
@Test
111122
public void testBadSequence() throws IOException, TimeoutException, InterruptedException, ExecutionException {
112123
synchronized (network.SERVER) {

0 commit comments

Comments
 (0)