Le texte a été révisé car le nom du terme UDF a été changé en Fonction. (10/01/2020)
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.
** 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. ** **
Ubuntu16.04 LTS (construit sur Windows 10 avec Hyper-V) Oracle Java 8
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
$ git clone https://github.com/scalar-labs/scalar-samples.git
$ cd scalar-samples
$ docker login
$ sudo docker-compose build
cent os 7
.$ 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
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
Ctrl + C
ou $ docker-compose down
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
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.
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.
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);
}
}
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
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.
$ ./gradlew assemble
Le fichier de classe de contrat est créé dans build / classes / java / main / com / org1 / contract / StateUpdater.class
.
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é.
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é.
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.
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):
Recommended Posts