Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
18 changes: 15 additions & 3 deletions exonum-java-binding/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,29 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]

### Added
- Support of creation of various blockchain proofs:
- Block Proof
- Transaction Execution Proof
- Call Result Proof
- Service Data Proof.

See [`Blockchain`][blockchain-proofs], `BlockProof` and `IndexProof`
for details. (#1355)
- Support of creation of Protobuf-based proofs for maps and lists.
Such proofs can be easily serialized using Protocol Buffers
and sent to the light clients.
See `ProofMapIndexProxy#getProof` and `MapProof`;
`ProofListIndexProxy.getProof`, `ProofListIndexProxy.getRangeProof` and
`ListProof`.
See:
- `ProofMapIndexProxy#getProof` and `MapProof`;
- `ProofListIndexProxy.getProof`, `ProofListIndexProxy.getRangeProof` and
`ListProof`;
- [`Blockchain`][blockchain-proofs].
- `ProofEntryIndexProxy` collection.
- `supervisor-mode` CLI parameter added for `generate-template` command. It
allows to configure the mode of the Supervisor service. Possible values are
"simple" and "decentralized". (#1361)

[blockchain-proofs]: https://exonum.com/doc/api/java-binding/0.10.0-SNAPSHOT/com/exonum/binding/core/blockchain/Blockchain.html#proofs

### Changed
- Transactions are now implemented as service methods annotated with
`@Transaction(TX_ID)`, instead of classes implementing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

package com.exonum.binding.common.message;

import static com.exonum.binding.common.hash.Hashing.sha256;

import com.exonum.binding.common.crypto.PublicKey;
import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.common.hash.Hashing;
import com.exonum.core.messages.Consensus;
import com.exonum.core.messages.Consensus.ExonumMessage;
import com.google.protobuf.ByteString;
Expand All @@ -31,7 +32,7 @@
* <p>It currently does not support verification of the signature against the author's public
* key — such functionality may be added later if needed.
*/
final class SignedMessage {
public final class SignedMessage {

private final ExonumMessage payload;
private final PublicKey authorPk;
Expand All @@ -56,10 +57,11 @@ private SignedMessage(ExonumMessage payload, PublicKey authorPk,
* {@link Consensus.SignedMessage}; or if the payload of the message is not
* {@link Consensus.ExonumMessage}
*/
static SignedMessage parseFrom(byte[] messageBytes) throws InvalidProtocolBufferException {
public static SignedMessage parseFrom(byte[] messageBytes) throws InvalidProtocolBufferException {
// Try to decode the SignedMessage container
HashCode hash = sha256().hashBytes(messageBytes);
Consensus.SignedMessage message = Consensus.SignedMessage.parseFrom(messageBytes);
return fromProto(message);
return fromProto(message, hash);
}

/**
Expand All @@ -69,26 +71,28 @@ static SignedMessage parseFrom(byte[] messageBytes) throws InvalidProtocolBuffer
* @throws InvalidProtocolBufferException if a signed message does not contain a valid payload
* that is a serialized {@link Consensus.ExonumMessage}
*/
static SignedMessage fromProto(Consensus.SignedMessage message)
public static SignedMessage fromProto(Consensus.SignedMessage message)
throws InvalidProtocolBufferException {
HashCode hash = sha256().hashBytes(message.toByteArray());
return fromProto(message, hash);
}

private static SignedMessage fromProto(Consensus.SignedMessage message,
HashCode messageHash) throws InvalidProtocolBufferException {
// Try to decode the payload, which is stored as bytes. It is expected to be an ExonumMessage
ByteString payloadBytes = message.getPayload();
ExonumMessage payload = ExonumMessage.parseFrom(payloadBytes);

PublicKey authorPk = PublicKey.fromBytes(message.getAuthor()
.getData()
.toByteArray());
ByteString signature = message.getSignature().getData();

HashCode hash = Hashing.sha256().hashBytes(message.toByteArray());

return new SignedMessage(payload, authorPk, signature, hash);
return new SignedMessage(payload, authorPk, signature, messageHash);
}

/**
* Returns the message payload.
*/
Consensus.ExonumMessage getPayload() {
public Consensus.ExonumMessage getPayload() {
return payload;
}

Expand All @@ -98,7 +102,7 @@ Consensus.ExonumMessage getPayload() {
* <p>The correctness of the signature is <strong>not</strong> verified against this key
* and must be done separately if needed.
*/
PublicKey getAuthorPk() {
public PublicKey getAuthorPk() {
return authorPk;
}

Expand All @@ -109,15 +113,15 @@ PublicKey getAuthorPk() {
* <p>The correctness of the signature is <strong>not</strong> verified against this key
* and must be done separately if needed.
*/
byte[] getSignature() {
public byte[] getSignature() {
return signature.toByteArray();
}

/**
* Returns the hash of the signed message, which is the hash of the protobuf-serialized
* representation.
*/
HashCode hash() {
public HashCode hash() {
return hash;
}
}
4 changes: 2 additions & 2 deletions exonum-java-binding/core/rust/src/storage/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use {
/// - index is not initialized (index have not been used before calling the method)
/// - index is not Merkelized
#[no_mangle]
pub extern "system" fn Java_com_exonum_binding_core_blockchain_Blockchain_nativeCreateIndexProof(
pub extern "system" fn Java_com_exonum_binding_core_blockchain_BlockchainProofs_nativeCreateIndexProof(
env: JNIEnv,
_: JObject,
snapshot_handle: jlong,
Expand Down Expand Up @@ -50,7 +50,7 @@ pub extern "system" fn Java_com_exonum_binding_core_blockchain_Blockchain_native
/// - there is no such block
/// - passed `snapshot_handle` is Fork handle
#[no_mangle]
pub extern "system" fn Java_com_exonum_binding_core_blockchain_Blockchain_nativeCreateBlockProof(
pub extern "system" fn Java_com_exonum_binding_core_blockchain_BlockchainProofs_nativeCreateBlockProof(
env: JNIEnv,
_: JObject,
snapshot_handle: jlong,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

package com.exonum.binding.core.blockchain;

import static com.exonum.binding.common.hash.Hashing.sha256;
import static com.google.common.base.Preconditions.checkState;

import com.exonum.binding.common.hash.HashCode;
import com.exonum.binding.core.blockchain.serialization.BlockSerializer;
import com.exonum.binding.core.blockchain.serialization.CoreTypeAdapterFactory;
import com.exonum.binding.core.service.Schema;
import com.google.auto.value.AutoValue;
Expand Down Expand Up @@ -95,7 +97,7 @@ public final boolean isEmpty() {
/**
* Root hash of exceptions occurred in the block.
*
* @see Blockchain#getCallErrors()
* @see Blockchain#getCallErrors(long)
*/
public abstract HashCode getErrorHash();

Expand All @@ -122,6 +124,27 @@ public static TypeAdapter<Block> typeAdapter(Gson gson) {
return new AutoValue_Block.GsonTypeAdapter(gson);
}

/**
* Creates a block from the block message.
* @param blockMessage a block
*/
public static Block fromMessage(com.exonum.core.messages.Blockchain.Block blockMessage) {
// Such implementation prevents a redundant deserialization of Block message
// (in BlockSerializer#fromBytes).
HashCode blockHash = sha256().hashBytes(blockMessage.toByteArray());
return BlockSerializer.newBlockInternal(blockMessage, blockHash);
}

/**
* Creates a block from the serialized block message.
* @param serializedBlock a serialized block message
* @throws IllegalArgumentException if the block bytes are not a serialized
* {@link com.exonum.core.messages.Blockchain.Block}
*/
public static Block parseFrom(byte[] serializedBlock) {
return BlockSerializer.INSTANCE.fromBytes(serializedBlock);
}

/**
* Creates a new block builder.
*/
Expand Down Expand Up @@ -172,7 +195,7 @@ public abstract static class Builder {
* Sets the blockchain state hash at the moment this block was committed. The blockchain
* state hash reflects the state of each service in the database.
*
* @see Schema#getStateHashes()
* @see Schema
*/
public abstract Builder stateHash(HashCode blockchainStateHash);

Expand Down
Loading