Skip to content

Exonum Java Binding 0.10.0

Pre-release
Pre-release
Compare
Choose a tag to compare
@atrykush atrykush released this 09 Apr 09:57
· 80 commits to master since this release

Overview

The main feature of Exonum Java 0.10.0 is enhanced support of dynamic services and
their lifetime. Service instances might be stopped and resumed now. While
stopped, the service does not process transactions and its API endpoints are
unavailable.

Most of the user-facing interfaces were reworked to facilitate access to the
database and transaction execution context, and more distinction between
storage access abstractions were added to enforce services isolation.

Finally, the support of Protobuf-serialized proofs has been re-enabled and
expanded since the last release.

If you are upgrading an existing Java service, consult the migration guide. If you are new to Exonum — see the new tutorial on service development.

This release is based on Exonum 1.0.0, the first
stable Exonum release. See release notes for details.

Added

  • Support of creation of various blockchain proofs:

    • Block Proof
    • Transaction Execution Proof
    • Call Result Proof
    • Service Data Proof.

    See Blockchain BlockProof and IndexProof
    for details. (#1355)

    • Proofs for executing service can be created with
      BlockchainData#createIndexProof directly by the index simple name.
  • 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;
    • Blockchain.
  • ProofEntryIndex collection and EntryIndex interface.

    • EntryIndex#orElse method.
  • Execution preconditions utility methods,
    see com.exonum.binding.core.service.ExecutionPreconditions. (#1351)

  • 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)

  • Support of service instances lifecycle: they can be activated, stopped and resumed now.
    Also, service instance artifacts can be upgraded before resuming which allows services
    API update, add new service transactions, synchronous data migration etc. (#1358, #1372)

  • BlockchainData — an object providing access to all categories of persistent data
    stored in the database: the executing service data, other services’ data,
    Exonum Core data. BlockchainData is a service-specific object — it remembers
    the service to which it is provided and allows modification only to the data
    of that service. The service data is automatically isolated via namespaces,
    with a service name followed by a dot as a prefix
    (see BlockchainData#getExecutingServiceData). (#1393)

  • Prefixed and ReadonlyFork database Accesses. (#1382, #1385)

  • Service#beforeTransactions.

  • KeyPair#newInstance(PrivateKey, PublicKey)

  • Blockchain#getNumTransactions, returning the total number of committed
    to the blockchain transactions.

  • Blockchain#getNextHeight, returning the height of the next committed block.

  • Configuration can be passed in several text-based formats: JSON, Java
    properties, plain text.
    The configuration parameters are transferred using a standard protobuf message
    ServiceConfiguration.
    exonum-launcher comes with built-in support for text-based configuration
    formats.

Changed

  • Transactions are now implemented as service methods annotated with
    @Transaction(TX_ID), instead of classes implementing
    Transaction interface. (#1274, #1307)
  • Any exceptions thrown from the Transaction methods
    but ExecutionException are saved with the error kind
    "unexpected" into Blockchain#getCallErrors.
  • Redefined TransactionExecutionException:
    • Renamed into ExecutionException and moved to package
      com.exonum.binding.core.service
    • Made TransactionExecutionException an unchecked (runtime) exception
    • Specified it as the exception to communicate execution errors
      of Service methods: @Transactions; Service#afterTransactions,
      #initialize; Configurable methods.
  • Similarly, redefined TransactionContext:
    • Renamed into ExecutionContext and moved to package
      com.exonum.binding.core.service
    • Replaced BlockchainData argument in transaction-like Service and
      Configurable methods with ExecutionContext. The BlockchainData
      remains accessible via TransactionContext#getBlockchainData,
      and service data via TransactionContext#getServiceData.
    • Made getTransactionMessageHash return Optional<HashCode;
      and getAuthorPk return Optional<PublicKey> because the context
      is also used for non-transaction methods. (#1462)
  • Renamed Service#beforeCommit into Service#afterTransactions.
  • Allowed throwing execution exceptions from Service#afterTransactions
    (ex. beforeCommit).
    Any exceptions thrown in these methods are saved in the blockchain
    in Blockchain#getCallErrors and can be retrieved by any services or
    light clients.
  • Blockchain#getTxResults is replaced by Blockchain#getCallErrors.
    • Use CallInBlocks to concisely create CallInBlocks.
  • The specification of Configurable operations and Service#initialize
    to require throwing ExecutionException instead of
    IllegalArgumentException.
  • Transaction index in block type changed from long to int. (#1348)
  • Extracted artifact version to the separate field from the artifact name.
    Artifact name format is groupId/artifactId now.
    PluginId format is runtimeId:artifactName:artifactVersion now. (#1349)
  • Extracted #getIndexHash into HashableIndex interface. (#1366)
  • Made Views (Fork and Snapshot) index factories. An index factory
    implements Access interface. Access allows instantiating various
    MerkleDB indexes, aka "collections" (e.g., Access#getList -> ListIndex).
    Access methods must be used to create indexes in service code.
    Factory methods in indexes must no longer be used (see also 'Removed'
    section below).
    • Use Access instead of View (which is renamed to AbstractAccess).
    • IndexAddresses are resolved relatively to Accesses (#1374)
  • Exonum protobuf messages are moved from exonum-java-binding-common
    to a new module com.exonum.messages:exonum-messages.
  • Java 11 is the minimum required version to run Exonum services.
    Client libraries: exonum-messages and exonum-java-binding-common remain
    Java 8 compatible.
  • The service archetype to produce a multi-module service template project,
    with a separate module for Protocol Buffers messages, so that they
    can be re-used in light clients; and a module for service code. (#1461)
  • ServiceArtifactId and RuntimeId are moved to
    com.exonum.binding.common.runtime package. (#1452)
  • Renamed the KeyPair factory methods to newInstance.

Removed

  • Classes supporting no longer used tree-like list proof representation.
  • Schema#getStateHashes and Service#getStateHashes methods. Framework
    automatically aggregates state hashes of the Merkelized collections.
  • TransactionConverter — it is no longer needed with transactions
    as Service methods annotated with @Transaction. Such methods may accept
    arbitrary protobuf messages as their argument. (#1304, #1307)
  • ExecutionStatuses factory methods (serviceError) as they are no longer
    useful to create expected transaction execution statuses in tests —
    an ExecutionError now has a lot of other properties.
    ExecutionStatuses.success is replaced with ExecutionStatuses.SUCCESS constant.
  • newInstance methods in all the indexes are made internal:
    • Use Access methods instead. E.g., instead of ProofListIndexProxy.newInstance
      use Access.getProofList.
    • Instead of using overloads accepting protobuf classes, create a serializer
      explicitly with StandardSerializers.protobuf.
    • To create index groups (aka families), pass a group address:
      IndexAddress.valueOf(String, byte[]). (#1374)
  • AbstractService#createDataSchema — just use the schema constructor/factory
    method, as passing the instance name is no longer required with the Prefixed
    DB Access. (#1393)

Known Issues

  • Java 14 is not supported as the runtime for Exonum Java services — see #1509.
    JDK 11 through 13 work fine.