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
3 changes: 3 additions & 0 deletions exonum-java-binding/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Support of Time oracle. Instruction on how to enable built-in services can be found
[here](https://exonum.com/doc/version/0.4/get-started/java-binding/#built-in-services). (#667)

### Changed
- `TransactionResult` and `TransactionLocation` classes moved to the common module. (#725)

## [0.4] - 2019-02-18

This release is based on the latest Exonum version, 0.10,
Expand Down
6 changes: 6 additions & 0 deletions exonum-java-binding/common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
* limitations under the License.
*/

package com.exonum.binding.blockchain;
package com.exonum.binding.common.blockchain;

import com.google.auto.value.AutoValue;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.SerializedName;

/**
* Transaction position in the blockchain. Enumeration begins from 0.
Expand All @@ -33,18 +34,20 @@ public static TransactionLocation valueOf(long height, long indexInBlock) {
/**
* Height of the block where the transaction was committed.
*/
@SerializedName("block_height")
public abstract long getHeight();

/**
* Zero-based position of this transaction in the block. Transactions executed in the ascending
* order of these indices.
*/
@SerializedName("position_in_block")
public abstract long getIndexInBlock();

/**
* Provides a Gson type adapter for this class.
*
* @see com.exonum.binding.blockchain.serialization.TransactionLocationAdapterFactory
* @see com.exonum.binding.common.serialization.json.TransactionLocationAdapterFactory
*/
public static TypeAdapter<TransactionLocation> typeAdapter(Gson gson) {
return new AutoValue_TransactionLocation.GsonTypeAdapter(gson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@
* limitations under the License.
*/

package com.exonum.binding.blockchain;
package com.exonum.binding.common.blockchain;

import static com.google.common.base.Preconditions.checkArgument;

import com.exonum.binding.transaction.TransactionExecutionException;
import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;

import java.util.OptionalInt;
import javax.annotation.Nullable;

Expand All @@ -32,8 +30,6 @@
* if execution has failed.
* Errors might be either service-defined or unexpected. Service-defined errors consist of an error
* code and an optional description. Unexpected errors include only a description.
*
* @see TransactionExecutionException
*/
@AutoValue
public abstract class TransactionResult {
Expand All @@ -60,9 +56,8 @@ public static TransactionResult successful() {
}

/**
* Creates a transaction result corresponding to a user-defined
* {@linkplain TransactionExecutionException exception} during transaction execution
* (or the corresponding Error in Rust services).
* Creates a transaction result corresponding to a user-defined exception
* during transaction execution (or the corresponding Error in Rust services).
*
* @param errorCode a user-defined error code; must be in range [0; 255]
* @param errorDescription an optional error description; may be null, which is considered
Expand Down Expand Up @@ -124,7 +119,7 @@ public boolean isSuccessful() {
/**
* Provides a Gson type adapter for this class.
*
* @see com.exonum.binding.blockchain.serialization.TransactionResultAdapterFactory
* @see com.exonum.binding.common.serialization.json.TransactionResultAdapterFactory
*/
public static TypeAdapter<TransactionResult> typeAdapter(Gson gson) {
return new AutoValue_TransactionResult.GsonTypeAdapter(gson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.exonum.binding.common.crypto.PublicKey;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.common.message.TransactionMessage;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.LongSerializationPolicy;
Expand All @@ -38,6 +39,8 @@ public final class JsonSerializer {
*/
public static GsonBuilder builder() {
return new GsonBuilder()
.registerTypeHierarchyAdapter(TransactionMessage.class,
new TransactionMessageJsonSerializer())
.registerTypeHierarchyAdapter(HashCode.class, new HashCodeJsonSerializer())
.registerTypeAdapter(PublicKey.class, new PublicKeyJsonSerializer())
.registerTypeAdapterFactory(StoredConfigurationAdapterFactory.create())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.exonum.binding.blockchain.serialization;
package com.exonum.binding.common.serialization.json;

import com.google.gson.TypeAdapterFactory;
import com.ryanharter.auto.value.gson.GsonTypeAdapterFactory;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.serialization.json;

import static com.google.common.base.Preconditions.checkNotNull;

import com.exonum.binding.common.message.TransactionMessage;
import com.google.common.io.BaseEncoding;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;

final class TransactionMessageJsonSerializer implements JsonSerializer<TransactionMessage>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are there any needs for TransactionMessage serialization to JSON in other ways?

Copy link
Contributor

Choose a reason for hiding this comment

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

Can't say 🤷‍♂️ @vitvakatu , @MakarovS ?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd leave it as it is for now.

JsonDeserializer<TransactionMessage> {
private static final BaseEncoding HEX_ENCODER = BaseEncoding.base16().lowerCase();

@Override
public JsonElement serialize(TransactionMessage src, Type typeOfSrc,
JsonSerializationContext context) {
checkNotNull(src, "Transaction message value is null");
byte[] bytes = src.toBytes();
String hex = HEX_ENCODER.encode(bytes);

return new JsonPrimitive(hex);
}

@Override
public TransactionMessage deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
checkNotNull(json, "Transaction message json input is null");
String hex = json.getAsString();
byte[] bytes = HEX_ENCODER.decode(hex);

return TransactionMessage.fromBytes(bytes);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.exonum.binding.blockchain.serialization;
package com.exonum.binding.common.serialization.json;

import com.google.gson.TypeAdapterFactory;
import com.ryanharter.auto.value.gson.GsonTypeAdapterFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
* limitations under the License.
*/

package com.exonum.binding.blockchain;
package com.exonum.binding.common.blockchain;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.exonum.binding.blockchain.TransactionResult.Type;
import com.exonum.binding.common.blockchain.TransactionResult.Type;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@

import static com.exonum.binding.common.serialization.json.JsonSerializer.json;
import static com.exonum.binding.test.Bytes.bytes;
import static com.exonum.binding.test.Bytes.fromHex;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.isJson;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.withJsonPath;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import com.exonum.binding.common.crypto.PublicKey;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.common.message.TransactionMessage;
import org.junit.jupiter.api.Test;

class JsonSerializerTest {
Expand Down Expand Up @@ -57,6 +59,18 @@ void hashCodeSerializesAsValue() {
assertJsonValue(json, "000102");
}

@Test
void transactionMessageSerializesAsValue() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Shan't we make round-trip tests?

There is one below.

String hex = "87095f09d413633626a4a5b903d7e8dbb7a9f54baa92eb77965c5ad0417d8d65000"
+ "000007f0000010292a0d0ed9368a70984098519cef6bde555e85eaf8105c561a6c0b9599fae"
+ "f4eb7b02155160f0c2598c97c42bc294599a2be34ce9ce66ba7baa11bfdaf06e5e0c";
TransactionMessage value = TransactionMessage.fromBytes(fromHex(hex));

String json = json().toJson(new Wrapper<>(value));

assertJsonValue(json, hex);
}

private static void assertJsonValue(String json, Object expectedValue) {
assertThat(json, isJson(withJsonPath("$.value", equalTo(expectedValue))));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2019 The Exonum Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.exonum.binding.common.serialization.json;

import static com.exonum.binding.common.crypto.CryptoFunctions.ed25519;
import static com.exonum.binding.common.serialization.json.JsonSerializer.json;
import static com.exonum.binding.test.Bytes.bytes;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

import com.exonum.binding.common.crypto.KeyPair;
import com.exonum.binding.common.message.TransactionMessage;
import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

class TransactionMessageGsonSerializerTest {

private static Gson gson;

@BeforeAll
static void setup() {
gson = JsonSerializer.builder()
.registerTypeHierarchyAdapter(TransactionMessage.class,
new TransactionMessageJsonSerializer())
.create();
}

@ParameterizedTest
@MethodSource("source")
void roundTripTest(TransactionMessage msg) {
String json = gson.toJson(msg);
TransactionMessage restoredMsg = json().fromJson(json, TransactionMessage.class);

assertThat(restoredMsg, is(msg));
}

private static List<TransactionMessage> source() {
KeyPair keys = ed25519().generateKeyPair();

return ImmutableList.of(
TransactionMessage.builder()
.serviceId(Short.MIN_VALUE)
.transactionId(Short.MAX_VALUE)
.payload(bytes())
.sign(keys, ed25519()),
TransactionMessage.builder()
.serviceId((short) 0)
.transactionId((short) 127)
.payload(bytes(0x00, 0x01, 0x02))
.sign(keys, ed25519())
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import static com.google.common.base.Preconditions.checkArgument;

import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.binding.common.configuration.StoredConfiguration;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.common.message.TransactionMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.exonum.binding.blockchain.serialization.BlockSerializer;
import com.exonum.binding.blockchain.serialization.TransactionLocationSerializer;
import com.exonum.binding.blockchain.serialization.TransactionResultSerializer;
import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.binding.common.configuration.StoredConfiguration;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.common.message.TransactionMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import static com.exonum.binding.common.serialization.StandardSerializers.protobuf;

import com.exonum.binding.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.serialization.Serializer;

public enum TransactionLocationSerializer implements Serializer<TransactionLocation> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

package com.exonum.binding.blockchain.serialization;

import static com.exonum.binding.blockchain.TransactionResult.MAX_USER_DEFINED_ERROR_CODE;
import static com.exonum.binding.blockchain.TransactionResult.SUCCESSFUL_RESULT_STATUS_CODE;
import static com.exonum.binding.blockchain.TransactionResult.UNEXPECTED_ERROR_STATUS_CODE;
import static com.exonum.binding.common.blockchain.TransactionResult.MAX_USER_DEFINED_ERROR_CODE;
import static com.exonum.binding.common.blockchain.TransactionResult.SUCCESSFUL_RESULT_STATUS_CODE;
import static com.exonum.binding.common.blockchain.TransactionResult.UNEXPECTED_ERROR_STATUS_CODE;
import static com.exonum.binding.common.serialization.StandardSerializers.protobuf;

import com.exonum.binding.blockchain.TransactionResult;
import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.binding.common.serialization.Serializer;

public enum TransactionResultSerializer implements Serializer<TransactionResult> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
* status of a failed transaction. See
* <a href="https://exonum.com/doc/version/0.10/advanced/node-management/#transaction">the API endpoint documentation</a>
* for more information.
*
* @see com.exonum.binding.common.blockchain.TransactionResult
*/
public class TransactionExecutionException extends Exception {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionResult;
import com.exonum.binding.common.configuration.StoredConfiguration;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.storage.indices.ListIndexProxy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

import com.exonum.binding.blockchain.TransactionLocation;
import com.exonum.binding.common.blockchain.TransactionLocation;
import com.exonum.binding.common.serialization.Serializer;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down
Loading