Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion exonum-light-client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## Unreleased

### Changed
- `TransactionResponse#getExecutionResult` now returns `ExecutionStatus`
instead of `TransactionResult`. (#1244)

## 0.4.0 — 2019-10-09

The new release of the light client brings support for Exonum 0.12
Expand All @@ -28,7 +32,7 @@ and Exonum Java 0.8.
- `ExonumClient#getBlockByHeight` and `#getBlocks` to throw
`IllegalArgumentException` when blocks with heights exceeding
the current blockchain height are requested (#1137)
- `Block` JSON representation to be compatible with the one used
- `Block` JSON representation to be compatible with the one used
for blocks by the core. Applied `@SerializedName` annotation
to all fields. (#1137)
- Updated project dependencies to the newest versions.
Expand Down
6 changes: 3 additions & 3 deletions exonum-light-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ The following example shows how to create the transaction message.
In addition please read about [transaction message structure][exonum-tx-message-builder].
```java
TransactionMessage txMessage = TransactionMessage.builder()
.serviceId((short) 1)
.transactionId((short) 2)
.serviceId(1)
.transactionId(2)
.payload(data)
.sign(keys, CryptoFunctions.ed25519());
.sign(keys);
```
* `data` is a bytes array which contains transactional information/parameters
in a service-defined format.
Expand Down
2 changes: 1 addition & 1 deletion exonum-light-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

<properties>
<!-- Project configuration -->
<ejb.version>0.8.0</ejb.version>
<ejb.version>0.9.0-SNAPSHOT</ejb.version>
<java.compiler.source>8</java.compiler.source>
<java.compiler.target>8</java.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
/**
* Main interface for Exonum Light client.
* Provides a convenient way for interaction with Exonum framework APIs.
* All the methods of the interface work in a blocking way
* i.e. invoke underlying request immediately, and block until the response can be processed
* All the methods of the interface work in a blocking way,
* i.e., invoke underlying request immediately, and block until the response can be processed
* or an error occurs. In case the thread is interrupted, the blocked methods will complete
* exceptionally.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,21 @@
package com.exonum.client;

import static com.exonum.client.ExonumApi.JSON;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.stream.Collectors.toList;

import com.exonum.binding.common.blockchain.ExecutionStatuses;
import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.common.message.TransactionMessage;
import com.exonum.client.response.Block;
import com.exonum.client.response.BlockResponse;
import com.exonum.client.response.BlocksResponse;
import com.exonum.client.response.TransactionResponse;
import com.exonum.client.response.TransactionStatus;
import com.exonum.core.messages.Runtime.ErrorKind;
import com.exonum.core.messages.Runtime.ExecutionError;
import com.exonum.core.messages.Runtime.ExecutionStatus;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does it come here? Is it a part of exonum-java-binding-common? I mean exonum.core. package

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a part of exonum-java-binding-common?

Yes, it is, but, ideally, it mustn't be a part of it, but a dependency of it. I think we shall extract the messages into a separate module (or modules, if we believe that some messages are not needed everywhere, e.g., supervisor messages, or merkledb messages) that will have not just have its own package, but its own release cadence (since the main reason for their release is a new Exonum release).

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.gson.JsonArray;
Expand Down Expand Up @@ -58,11 +62,11 @@ static HashCode parseSubmitTxResponse(String json) {

static TransactionResponse parseGetTxResponse(String json) {
GetTxResponse response = JSON.fromJson(json, GetTxResponse.class);
TransactionResult executionResult = getTransactionResult(response.getStatus());
ExecutionStatus executionResult = getExecutionStatus(response.getStatus());

return new TransactionResponse(
response.getType(),
response.getContent().getMessage(),
response.getContent(),
executionResult,
response.getLocation()
);
Expand All @@ -87,25 +91,48 @@ static BlocksResponse parseGetBlocksResponse(String json) {
);
}

private static TransactionResult getTransactionResult(
private static ExecutionStatus getExecutionStatus(
GetTxResponseExecutionResult executionStatus) {
if (executionStatus == null) {
return null;
}
switch (executionStatus.getType()) {
case SUCCESS:
return TransactionResult.successful();
case ERROR:
return TransactionResult.error(executionStatus.getCode(),
executionStatus.getDescription());
return ExecutionStatuses.success();
case PANIC:
return TransactionResult.unexpectedError(executionStatus.getDescription());
return buildPanicExecutionStatus(executionStatus.getDescription());
case DISPATCHER_ERROR:
return buildExecutionStatus(ErrorKind.DISPATCHER, executionStatus.getCode(),
executionStatus.getDescription());
case RUNTIME_ERROR:
return buildExecutionStatus(ErrorKind.RUNTIME, executionStatus.getCode(),
executionStatus.getDescription());
case SERVICE_ERROR:
return ExecutionStatuses.serviceError(executionStatus.getCode(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not complete — see below.

executionStatus.getDescription());
default:
throw new IllegalStateException("Unexpected transaction execution status: "
+ executionStatus.getType());
}
}

@VisibleForTesting
static ExecutionStatus buildPanicExecutionStatus(String description) {
return buildExecutionStatus(ErrorKind.PANIC, 0, description);
}

@VisibleForTesting
static ExecutionStatus buildExecutionStatus(ErrorKind errorKind, int code,
String description) {
checkArgument(0 <= code, "Error code (%s) must be non-negative", code);
return ExecutionStatus.newBuilder()
.setError(ExecutionError.newBuilder()
.setKind(errorKind)
.setCode(code)
.setDescription(description))
.build();
}

/**
* Json object wrapper for submit transaction request.
*/
Expand All @@ -130,25 +157,14 @@ private static class GetTxResponse {
@NonNull
TransactionStatus type;
@NonNull
GetTxResponseContent content;
TransactionMessage content;
TransactionLocation location;
JsonObject locationProof; //TODO: in scope of LC P3
GetTxResponseExecutionResult status;
}

/**
* Json object wrapper for get transaction response content i.e.
* {@code "$.content"}.
*/
@Value
private static class GetTxResponseContent {
JsonObject debug; // contains executable tx in json. currently not supported
@NonNull
TransactionMessage message;
}

/**
* Json object wrapper for transaction execution result i.e.
* Json object wrapper for transaction execution result, i.e.,
* {@code "$.status"}.
*/
@Value
Expand All @@ -159,16 +175,20 @@ private static class GetTxResponseExecutionResult {
}

/**
* Json object wrapper for transaction execution status i.e.
* Json object wrapper for transaction execution status, i.e.,
* {@code "$.status.type"}.
*/
private enum GetTxResponseExecutionStatus {
@SerializedName("success")
SUCCESS,
@SerializedName("error")
ERROR,
@SerializedName("panic")
PANIC
PANIC,
@SerializedName("dispatcher_error")
DISPATCHER_ERROR,
@SerializedName("runtime_error")
RUNTIME_ERROR,
@SerializedName("service_error")
SERVICE_ERROR
}

@Value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
*/
public enum ConsensusStatus {
/**
* Shows that consensus is active
* i.e. it is enabled and the node has enough connected peers.
* Shows that consensus is active,
* i.e., it is enabled and the node has enough connected peers.
*/
ACTIVE,
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.exonum.client.response;

import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.core.messages.Runtime.ExecutionStatus;
import com.google.gson.annotations.SerializedName;

/**
Expand All @@ -31,7 +31,7 @@ public enum TransactionStatus {
/**
* Shows that transaction is committed to the blockchain.
* Please note that a committed transaction has not necessarily completed
* successfully — use the {@linkplain TransactionResult execution result}
* successfully — use the {@linkplain ExecutionStatus execution result}
* to check that.
*/
@SerializedName("committed")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ public Optional<ZonedDateTime> getCommitTime() {
return Optional.ofNullable(commitTime);
}


/**
* Returns true if this block is empty:
* contains no {@linkplain #getNumTransactions() transactions}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import static com.google.common.base.Preconditions.checkState;

import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.binding.common.message.TransactionMessage;
import com.exonum.core.messages.Runtime.ExecutionStatus;
import com.google.common.base.Objects;
import lombok.Value;

Expand All @@ -39,7 +39,7 @@ public class TransactionResponse {
* Transaction execution result.
* Not available unless the transaction is {@linkplain #isCommitted committed} to the blockchain.
*/
TransactionResult executionResult;
ExecutionStatus executionResult;
/**
* Transaction location in the blockchain.
* Not available unless the transaction is {@linkplain #isCommitted committed} to the blockchain.
Expand All @@ -50,7 +50,7 @@ public class TransactionResponse {
* Returns transaction execution result.
* @throws IllegalStateException if the transaction is not committed yet
*/
public TransactionResult getExecutionResult() {
public ExecutionStatus getExecutionResult() {
checkState(status == COMMITTED,
"Transaction result is available for committed transactions only");
return executionResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ void submitTransactionTest() throws InterruptedException {
// Create request
KeyPair keys = ed25519().generateKeyPair();
TransactionMessage txMessage = TransactionMessage.builder()
.serviceId((short) 1)
.transactionId((short) 2)
.serviceId(1)
.transactionId(2)
.payload(new byte[]{0x00, 0x01, 0x02})
.sign(keys, ed25519());
.sign(keys);
// Mock response
String hash = "f128c720e04b8243";
String mockResponse = "{\"tx_hash\":\"" + hash + "\"}";
Expand Down Expand Up @@ -160,16 +160,7 @@ void getTransaction() throws InterruptedException {
TransactionMessage expectedMessage = createTransactionMessage();
String mockResponse = "{\n"
+ " 'type': 'in-pool',\n"
+ " 'content': {\n"
+ " 'debug': {\n"
+ " 'to': {\n"
+ " 'data': []\n"
+ " },\n"
+ " 'amount': 10,\n"
+ " 'seed': 9587307158524814255\n"
+ " },\n"
+ " 'message': '" + toHex(expectedMessage) + "'\n"
+ " }\n"
+ " 'content': '" + toHex(expectedMessage) + "'\n"
+ "}";
server.enqueue(new MockResponse().setBody(mockResponse));

Expand Down
Loading