Der Text wurde überarbeitet, da der Name des UDF-Begriffs in Funktion geändert wurde. (2020/1/10)
Von Scalar entwickelte Blockchain-inspirierte Software für verteilte Hauptbuchplattformen.
(Referenz) Scalar DLT | Scalar, Inc. Scalar DL Docs
Ähnlich wie Blockchain, da es manipulationssicher und dezentral ist, verfügt Scalar DL über die folgenden zusätzlichen Funktionen:
Gleichzeitig werden einige Einschränkungen festgelegt, um ein unbeabsichtigtes Vertragsverhalten von Designern und Entwicklern zu verhindern.
Das Ausführungsergebnis des von Scalar DL ausgeführten Smart Contract wird von Scalar DB verwaltet, der vom Unternehmen entwickelten Software für die verteilte Datenbankverwaltung.
Versuchen Sie, Scalar DB unter WSL Ubuntu (Environment Construction) auszuführen
Dieses Mal wurde dieser Scalar DL aktualisiert, und es wurde gesagt, dass ein einzigartiger Mechanismus namens Function (später beschrieben), den andere Blockchains und ähnliche Dienste nicht haben, hinzugefügt wurde, also habe ich tatsächlich versucht, ihn mit Docker auszuführen.
** Ab Dezember 2019 wird Scalar DL nur noch als kommerzielle Lizenz angeboten. Sie müssen sich daher für die tatsächliche Verwendung separat an Scalar wenden. ** **.
Ubuntu16.04 LTS (basierend auf Windows 10 mit Hyper-V) Oracle Java 8
Ein Docker-Container wird von Scalar als Ausführungsumgebung für Scalar DL bereitgestellt. https://scalardl.readthedocs.io/en/latest/installation-with-docker/
Docker Engine und Docker Compose sind erforderlich, um den Docker-Container zu starten. Installieren Sie ihn daher unter Bezugnahme auf die folgende Site. https://docs.docker.com/install/ https://docs.docker.com/compose/install/
Sie benötigen auch eine Java-Ausführungsumgebung.
$ 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
$ docker-compose up
Wenn Sie am Ende die Option -d
hinzufügen, können Sie sie im Hintergrund starten. Da Sie jedoch keine weiteren Vorgänge ausführen können, bis der Start von Cassandra abgeschlossen ist, ist es besser, das Protokoll anzuzeigen und den Start zu überprüfen. Ist fertig.
Wenn während der Ausführung ein Fehler wie "Es gibt keine ausführbare Datei" angezeigt wird, überprüfen Sie die Ausführungsberechtigung der Datei und erteilen Sie die entsprechende Ausführungsberechtigung.
$ chmod +x /path/to/file
Sie müssen den Cassandra-Server mit dem anfänglichen Schema laden, das für die Verwendung von Scalar DL erforderlich ist. Dieser Befehl muss beim ersten Start nur einmal ausgeführt werden.
$ docker-compose exec cassandra cqlsh -f /create_schema.cql
Strg + C
oder $ Docker-Compose Down
Bearbeiten Sie scalar-samples / conf / client.properties und konfigurieren Sie die Eigenschaftendatei. Das Folgende sind die Mindesteinstellungen.
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
Bearbeiten Sie die folgenden Elemente entsprechend Ihrer Umgebung
Der Scalar DL-Vertrag ist eine Java-Klasse, die die Contract-Klasse erweitert und die Aufrufmethode überschreibt. Dieses Mal wird als Beispiel, wenn Asset_ID und Status eingegeben werden, ein Beispielvertrag erstellt, der Status als Wert in dem von Asset_ID angegebenen Asset registriert.
$ 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;
}
}
Das Verfahren zum Kompilieren und Ausführen wird später beschrieben.
Es ist ein Programm, das in Java geschrieben ist. Get, Put und Delete können für Scalar DB innerhalb derselben Transaktion wie die Vertragsausführung ausgeführt werden.
Mit anderen Worten, was getan werden kann, ist, dass Function "sowohl die Verarbeitung unveränderlicher Daten, die Manipulationssicherheit erfordert, als auch die Verarbeitung veränderlicher Daten, die Änderungen in derselben Transaktion erfordern, realisieren kann". werden.
Beim Entwerfen und Implementieren ist es möglich, auf das Argument des Vertrags in der Funktion zu verweisen und es für die Verarbeitung zu verwenden. Es ist jedoch zu beachten, dass auf das Argument der Funktion auf der Vertragsseite nicht Bezug genommen werden kann.
Holen Sie sich "Asset_ID" und "State" aus dem Argument des Vertrags, erhalten Sie "User_id" aus dem Argument der Funktion und erstellen Sie eine Funktion, die "Asset_ID" mit "User_id" und "State" als Schlüssel registriert.
$ 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);
}
}
Die Funktion erstellt ein Schema zum Registrieren von Werten in Scalar DB. Das hier erstellte Schema muss jedoch ein Schema sein, das der Transaktion entspricht. Referenz: Scalar DB Docs - Interne Metadaten in Scalar DB
Die Schemaerstellung erfolgt durch Eingabe von Befehlen aus der Cassandra-Shell
$ 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)
);
Überprüfen Sie die erstellte Tabelle
cqlsh> use test;
cqlsh:test> describe tables;
test_schema
Um einen Vertrag oder eine Funktion auszuführen, muss für jeden Vertrag oder jede Funktion eine eindeutige ID angegeben, mit einem privaten Schlüssel signiert und in Scalar DL registriert werden. Mit diesem Mechanismus wird klar, wer ihn ausgeführt hat, und es ist möglich, die Ausführung nicht autorisierter Benutzer zu verhindern.
$ ./gradlew assemble
Die Vertragsklassendatei wird in build / classes / java / main / com / org1 / contract / StateUpdater.class
erstellt.
Es steht ein einfaches Tool zur Registrierung zur Verfügung. Verwenden Sie es also. Bei der Registrierung benötigen Sie den Pfad der Eigenschaftendatei, die ID des global eindeutigen Vertrags, den Binärnamen des Vertrags und den Pfad der Klassendatei.
$ 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
Bei Erfolg wird "Status: 200" angezeigt.
Registrieren Sie sich mit demselben Tool wie im Vertrag. Gleiches gilt für den Eigenschaftendateipfad, die global eindeutige ID, den Binärnamen und den Klassendateipfad.
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
Bei Erfolg wird "Status: 200" angezeigt.
Führen Sie den im obigen Verfahren registrierten Vertrag und die Funktion aus. Es wird auch vom Tool ausgeführt, und das Argument des Vertrags wird durch die Option "-contract-argument" angegeben und hat das Format "functions": "Funktions-ID1", "Funktions-ID2", ... " Geben Sie die Funktion an, die in derselben Transaktion ausgeführt werden soll. In Function verwendete Argumente werden durch die Option -function-argument
angegeben.
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"}'
Wenn die Ausführung erfolgreich ist, wird "Status: 200" angezeigt.
Beachten Sie, dass die Funktion das Schema auch nicht aktualisiert, wenn der Vertrag das Asset nicht aktualisiert.
Überprüfen Sie nach der Ausführung des Vertrags, ob er problemlos ausgeführt wurde. Implementieren Sie für das Ausführungsergebnis des Vertrags den Vertrag, der den neuesten Wert des Vermögenswerts erfasst, registrieren Sie ihn, führen Sie ihn aus und überprüfen Sie ihn.
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();
}
}
Vertragsregistrierung
$ 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
Bei Erfolg wird "Status: 200" angezeigt.
Lauf
client/bin/execute-contract -properties conf/client.properties -contract-id StateReader -contract-argument '{"asset_id": "my_asset"}'
Bei korrekter Ausführung sollte "state": {"state": 1} "angezeigt werden.
Überprüfen Sie das Cassandra-Schema direkt, um die Ausführung der Funktion zu überprüfen.
$ docker-compose exec cassandra cqlsh
cqlsh> select * from test.test_schema;
Bei korrekter Ausführung sollten Sie ähnliche Ergebnisse erhalten (Werte wie "tx_id" sind wahrscheinlich unterschiedlich):
Recommended Posts