[JAVA] J'ai essayé d'utiliser Scalar DL avec Docker

Le texte a été révisé car le nom du terme UDF a été changé en Fonction. (10/01/2020)

Qu'est-ce que Scalar DL?

Logiciel de plate-forme de grand livre distribué inspiré de la blockchain développé par Scalar.

(référence) Scalar DLT | Scalar, Inc. Scalar DL Docs

Semblable à la blockchain en ce qu'elle est inviolable et décentralisée, Scalar DL possède les fonctionnalités supplémentaires suivantes:

Dans le même temps, certaines restrictions sont définies pour empêcher le comportement contractuel involontaire des concepteurs et des développeurs.

Le résultat de l'exécution du contrat intelligent exécuté par Scalar DL est géré par Scalar DB, qui est le logiciel de gestion de bases de données distribuées développé par l'entreprise.

Essayez d'exécuter Scalar DB sur WSL Ubuntu (Construction de l'environnement)

Cette fois, ce Scalar DL a été mis à jour, et il a été dit qu'un mécanisme unique (décrit plus tard) appelé Function, qui ne se trouve pas dans d'autres blockchains et services similaires, a été ajouté, alors j'ai en fait essayé de l'exécuter avec docker.

Mise en garde

** Depuis décembre 2019, Scalar DL est fourni uniquement sous forme de licence commerciale, vous devez donc contacter Scalar séparément pour une utilisation réelle. ** **

Formulaire de contact

Environnement de développement

Ubuntu16.04 LTS (construit sur Windows 10 avec Hyper-V) Oracle Java 8

Préparation préalable

Un conteneur Docker est fourni par Scalar comme environnement d'exécution pour Scalar DL. https://scalardl.readthedocs.io/en/latest/installation-with-docker/

Docker Engine et Docker Compose sont nécessaires pour démarrer le conteneur Docker, donc installez-le en vous référant au site suivant. https://docs.docker.com/install/ https://docs.docker.com/compose/install/

Vous avez également besoin d'un environnement d'exécution Java.

$ apt update
$ sudo apt install openjdk-8-jdk

Préparation à l'exécution de Scalar DL

clone du référentiel d'échantillons scalaires

$ git clone https://github.com/scalar-labs/scalar-samples.git
$ cd scalar-samples

S'identifier

$ docker login

Construction de service

$ sudo docker-compose build

Démarrer le conteneur

$ docker-compose up

Si vous ajoutez l'option -d à la fin, vous pouvez la démarrer en arrière-plan, mais comme vous ne pouvez pas effectuer d'autres opérations tant que le démarrage de Cassandra n'est pas terminé, il est préférable d'afficher le journal et de vérifier le début. Est fait.

Si une erreur telle que "Il n'y a pas de fichier exécutable" apparaît pendant l'exécution, vérifiez l'autorisation d'exécution du fichier et accordez l'autorisation d'exécution le cas échéant. $ chmod +x /path/to/file

Chargement du schéma initial

Vous devez charger le serveur Cassandra avec le schéma initial nécessaire pour utiliser Scalar DL. Cette commande ne doit être exécutée qu'une seule fois au premier démarrage. $ docker-compose exec cassandra cqlsh -f /create_schema.cql

Arrêter le conteneur

Ctrl + C ou $ docker-compose down

Modifier le fichier de propriétés

Modifiez scalar-samples / conf / client.properties et configurez le fichier de propriétés. Voici les paramètres minimum.

client.properties


# A host name of Scalar DL network server.
scalar.ledger.client.server_host=localhost

# An ID of a certificate holder. It must be configured for each private key and unique in the system.
scalar.ledger.client.cert_holder_id=foo

# A certificate file path to use.
scalar.ledger.client.cert_path=/path/to/foo.pem

# A private key file path to use. 
scalar.ledger.client.private_key_path=/path/to/foo-key.pem

Modifiez les éléments suivants en fonction de votre environnement

Créer un contrat

Le contrat Scalar DL est une classe Java qui étend la classe Contract et remplace la méthode invoke. Cette fois, à titre d'exemple, lorsque asset_id et state sont saisis, un exemple de contrat qui enregistre l'état en tant que valeur dans l'actif spécifié par asset_id est créé.

$ vi src/main/java/com/org1/contract/StateUpdater.java

StateUpdater.java


package com.org1.contract;

import com.scalar.ledger.asset.Asset;
import com.scalar.ledger.contract.Contract;
import com.scalar.ledger.exception.ContractContextException;
import com.scalar.ledger.ledger.Ledger;
import java.util.Optional;
import javax.json.Json;
import javax.json.JsonObject;

public class StateUpdater extends Contract {
  @Override
  public JsonObject invoke(Ledger ledger, JsonObject argument, Optional<JsonObject> properties) {

    if (!argument.containsKey("asset_id") || !argument.containsKey("state")) {
      // ContractContextException is the only throwable exception in a contract and
      // it should be thrown when a contract faces some non-recoverable error
      throw new ContractContextException("please set asset_id and state in the argument");
    }

    String assetId = argument.getString("asset_id");
    int state = argument.getInt("state");

    Optional<Asset> asset = ledger.get(assetId);

    if (!asset.isPresent() || asset.get().data().getInt("state") != state) {
      ledger.put(assetId, Json.createObjectBuilder().add("state", state).build());
    }
    return null;
  }
}

La procédure de compilation et d'exécution sera décrite plus loin.

Créer une fonction et un schéma utilisés par la fonction

Quelle est la fonction

C'est un programme écrit en langage Java. Get, Put et Delete peuvent être exécutés pour Scalar DB dans la même transaction que l'exécution du contrat.

En d'autres termes, ce qui peut être fait, c'est que Function peut «réaliser à la fois un traitement de données immuables qui nécessite une résistance à la falsification et un traitement de données mutables qui nécessite un changement dans la même transaction». devenir.

Lors de la conception et de la mise en œuvre, il est possible de se référer à l'argument du contrat dans la fonction et de l'utiliser pour le traitement, mais il convient de noter que l'argument de la fonction ne peut pas être mentionné du côté du contrat.

Exemple de fonction

Récupérez ʻasset_id et state à partir de l'argument du contrat, obtenez ʻuser_id à partir de l'argument de Function, et créez une fonction qui enregistre ʻasset_id avec ʻuser_id et state comme clés.

$ vi src/main/java/com/scalar/ist/function/SchemaUpdater.java

SchemaUpdater.java


package com.scalar.ist.function;

import com.scalar.database.api.Get;
import com.scalar.database.api.Put;
import com.scalar.database.api.Result;
import com.scalar.database.io.IntValue;
import com.scalar.database.io.Key;
import com.scalar.database.io.TextValue;
import com.scalar.ledger.database.MutableDatabase;
import com.scalar.ledger.udf.Function;
import java.util.Optional;
import javax.json.JsonObject;

public class SchemaUpdater extends Function {
  @Override
  public void invoke(
    MutableDatabase database,
    JsonObject contractArgument,
    Optional<JsonObject> functionArgument) {

    String userId = functionArgument.get().getString("user_id");
    int state = contractArgument.getInt("state");
    String assetId = contractArgument.getString("asset_id");

    Get get =
      new Get(
        new Key(new TextValue("user_id", userId)),
        new Key(new IntValue("state", state)))
        .forNamespace("test")
        .forTable("test_schema");
    database.get(get);

    Put put =
      new Put(
        new Key(new TextValue("user_id", userId)),
        new Key(new IntValue("state", state)))
        .withValue(new TextValue("value",assetId))
        .forNamespace("test")
        .forTable("test_schema");
    database.put(put);
  }
}

Création d'un schéma à utiliser avec une fonction

Function crée un schéma pour l'enregistrement des valeurs dans Scalar DB. Cependant, le schéma créé ici doit être un schéma correspondant à la transaction. Référence: Scalar DB Docs --Métadonnées internes dans Scalar DB

La création de schéma se fait en entrant des commandes depuis le shell Cassandra

$ docker-compose exec cassandra cqlsh
cqlsh> create table test.test_schema	
 (
  user_id text,
  state int,
  value text,
  before_value text,

  before_tx_committed_at bigint,
  before_tx_id text,
  before_tx_prepared_at bigint,
  before_tx_state int,
  before_tx_version int,
  tx_committed_at bigint,
  tx_id text,
  tx_prepared_at bigint,
  tx_state int,
  tx_version int,
  primary key (user_id, state)
 );

Vérifiez la table créée

cqlsh> use test;
cqlsh:test> describe tables;

test_schema

Enregistrement / exécution des contrats et des fonctions

Afin d'exécuter un contrat ou une fonction, il est nécessaire de spécifier un ID unique pour chaque contrat ou fonction, le signer avec une clé privée et l'enregistrer dans Scalar DL. Avec ce mécanisme, il devient clair qui l'a exécuté et il est possible d'empêcher l'exécution d'utilisateurs non autorisés.

compiler

$ ./gradlew assemble

Le fichier de classe de contrat est créé dans build / classes / java / main / com / org1 / contract / StateUpdater.class.

Enregistrement du contrat

Un outil simple d'enregistrement est disponible, alors utilisez-le. Lors de l'inscription, vous aurez besoin du chemin du fichier de propriétés, de l'ID du contrat globalement unique, du nom binaire du contrat et du chemin du fichier de classe.

$ client/bin/register-contract -properties conf/client.properties -contract-id StateUpdater -contract-binary-name com.org1.contract.StateUpdater -contract-class-file build/classes/java/main/com/org1/contract/StateUpdater.class

En cas de succès, status: 200 sera affiché.

Enregistrement des fonctions

Inscrivez-vous en utilisant le même outil que le contrat. Il en va de même pour le chemin du fichier de propriétés, l'ID unique global, le nom binaire et le chemin du fichier de classe.

client/bin/register-function -properties conf/client.properties -function-id SchemaUpdater -function-binary-name com.scalar.ist.function.SchemaUpdater -function-class-file build/classes/java/main/com/scalar/ist/function/SchemaUpdater.class

En cas de succès, status: 200 sera affiché.

Courir

Exécutez le contrat et la fonction enregistrés dans la procédure ci-dessus. Il est également exécuté par l'outil, et l'argument du contrat est spécifié par l'option -contract-argument, sous la forme de" _functions_ ": [" Function ID1 "," Function ID2 ", ...](array) Spécifiez la fonction à exécuter dans la même transaction. Les arguments utilisés dans Function sont spécifiés par l'option -function-argument.

client/bin/execute-contract -properties conf/client.properties -contract-id StateUpdater -contract-argument '{"asset_id": "my_asset", "state": 1, "_functions_": ["SchemaUpdater"]}' -function-argument '{"user_id": "john"}'

Si l'exécution réussit, status: 200 s'affiche.

Notez que si le contrat ne met pas à jour l'actif, la fonction ne mettra pas non plus à jour le schéma.

Vérification

Après avoir exécuté le contrat, vérifiez s'il a été exécuté sans problème. Pour le résultat de l'exécution du contrat, mettez en œuvre le contrat qui acquiert la dernière valeur de l'actif, enregistrez-le, exécutez-le et vérifiez-le.

StateReader.java


package com.org1.contract;

import com.scalar.ledger.asset.Asset;
import com.scalar.ledger.asset.InternalAsset;
import com.scalar.ledger.contract.Contract;
import com.scalar.ledger.ledger.Ledger;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import java.util.Optional;

public class StateReader extends Contract {

  @Override
  public JsonObject invoke(Ledger ledger, JsonObject argument, Optional<JsonObject> properties) {
    String assetId = argument.getString("asset_id");

    Optional<Asset> asset = ledger.get(assetId);
    InternalAsset internal = (InternalAsset) asset.get();

    JsonObjectBuilder builder = Json.createObjectBuilder()
        .add("state", internal.data());

    return builder.build();
  }
}

Enregistrement du contrat

$ client/bin/register-contract -properties conf/client.properties -contract-id StateReader -contract-binary-name com.org1.contract.StateReader -contract-class-file build/classes/java/main/com/org1/contract/StateReader.class

En cas de succès, status: 200 sera affiché.

Courir

client/bin/execute-contract -properties conf/client.properties -contract-id StateReader -contract-argument '{"asset_id": "my_asset"}'

S'il est exécuté correctement, vous devriez voir "" state ": {" state ": 1}`.

Pour vérifier l'exécution de Function, vérifiez directement le schéma Cassandra.

$ docker-compose exec cassandra cqlsh
cqlsh> select * from test.test_schema;

Si cela est fait correctement, vous devriez obtenir des résultats similaires aux suivants (les valeurs telles que tx_id sont probablement différentes): image.png

Recommended Posts

J'ai essayé d'utiliser Scalar DL avec Docker
J'ai essayé BIND avec Docker
J'ai essayé d'utiliser JOOQ avec Gradle
J'ai essayé d'utiliser Realm avec Swift UI
J'ai essayé d'utiliser OnlineConverter avec SpringBoot + JODConverter
J'ai essayé d'utiliser OpenCV avec Java + Tomcat
J'ai essayé d'utiliser Gson
J'ai essayé d'utiliser TestNG
J'ai essayé d'utiliser Galasa
J'ai essayé de vérifier AdoptOpenJDK 11 (11.0.2) avec l'image Docker
J'ai fait un blackjack avec Ruby (j'ai essayé d'utiliser minitest)
J'ai essayé DI avec Ruby
J'ai essayé d'utiliser azure cloud-init
J'ai essayé d'utiliser Apache Wicket
J'ai essayé d'utiliser Java REPL
J'ai essayé UPSERT avec PostgreSQL.
Utilisation de PlantUml avec Honkit [Docker]
J'ai essayé de construire l'environnement petit à petit en utilisant docker
J'ai essayé de créer un environnement de développement padrino avec Docker
J'ai essayé de démarrer avec Swagger en utilisant Spring Boot
J'ai essayé d'utiliser la bibliothèque CameraX avec Android Java Fragment
J'ai essayé d'utiliser anakia + Jing maintenant
J'ai essayé d'utiliser Spring + Mybatis + DbUnit
J'ai essayé l'analyse morphologique avec MeCab
J'ai essayé d'interagir avec Java
J'ai essayé la communication UDP avec Java
J'ai essayé d'utiliser l'API Java8 Stream
J'ai essayé d'utiliser JWT en Java
J'ai essayé GraphQL avec Spring Boot
[Android] J'ai essayé d'utiliser la disposition du coordinateur.
J'ai essayé Flyway avec Spring Boot
J'ai essayé d'utiliser le conteneur Pari gp
J'ai essayé d'utiliser WebAssembly Stadio (version 2018/4/17)
Utilisation de cuda11.0 avec pytorch en utilisant Docker
J'ai essayé de personnaliser Slim avec Scaffold
J'ai essayé d'utiliser le mémo Java LocalDate
J'ai essayé d'utiliser Google HttpClient de Java
J'ai essayé d'intégrer parfaitement Docker et Maven / Netbean en utilisant Jib
J'ai essayé de créer un environnement de serveur UML Plant avec Docker
J'ai essayé de me connecter à MySQL en utilisant le modèle JDBC avec Spring MVC
J'ai essayé d'utiliser l'API Elasticsearch en Java
J'ai essayé d'utiliser UICollectionViewListCell ajouté à partir de Xcode12.
J'ai essayé de démarrer avec Web Assembly
Serveur proxy par squid en utilisant l'image docker
J'ai essayé l'apprentissage de la gestion qui fait gagner du temps avec Studyplus.
C'est nouveau, mais j'ai essayé d'utiliser Groonga
J'ai essayé de jouer un peu avec BottomNavigationView ①
J'ai essayé l'initialisation paresseuse avec Spring Boot 2.2.0
Reconnaissance GPU avec docker utilisant WSL2 (août 2020)
Qu'est-ce que Docker? J'ai essayé de résumer