5 sposobów, w jakie rozwój aplikacji Ergo zmienił się na zawsze dzięki Appkit
3 grudnia 2019

Dzięki Robertowi Kornackiemu i Denysowi Zadorozhnyi.
Ergo Appkit to biblioteka do
wielojęzycznego rozwoju aplikacji Ergo opartej na
GraalVM. GraalVM ma wiele świetnych
przykładów użycia. Rozwijając to, w tym artykule przejdziemy przez niektóre z funkcji Appkit
odziedziczone po GraalVM i krok po kroku nauczymy się, jak z nich korzystać.
- 0. Przykładowy scenariusz
- 1. Rozwój aplikacji Java Ergo
- 2. Aplikacje Ergo o niskim zużyciu zasobów i szybkim uruchamianiu
- 3. Rozwój aplikacji Ergo w JavaScript, Pythonie, Ruby
- 4. Natywne biblioteki współdzielone Ergo
- 5. Debugowanie aplikacji Ergo w wielu językach
Przykładowy scenariusz
Stworzymy prostą aplikację konsolową (nazywaną
FreezeCoin)
w języku Java, która wykorzystuje bibliotekę Appkit. Dzięki Appkit będziemy mogli łatwo wysłać nową transakcję do węzła Ergo programowo. Transakcja
przeniesie określoną ilość Erg do nowego pudełka chronionego przez
następujący kontrakt Ergo napisany w ErgoScript (zobacz to
wdrożenie i więcej zaawansowanych
przykładów, aby dowiedzieć się więcej o ErgoScript).
// Kontrakt Freezera
{
// Parametry
// freezeDeadline: Int - numer bloku w przyszłości, po którym pudełko może być wydane
// ownerPk: SigmaProp - klucz publiczny nowego właściciela pudełka
sigmaProp(HEIGHT > freezeDeadline) && ownerPk
}
Krótko mówiąc, pudełko (a zatem środki w pudełku) są zablokowane pod kontraktem (lub skryptem) na blockchainie Ergo. Aby pudełko mogło być wydane, kontrakt musi ocenić się na prawdę. Dlatego osoba, która chce wydać pudełko, musi upewnić się, że kontrakt ocenia się na prawdę na podstawie zakodowanej logiki w nim.
Nasz kontrakt Freezera powyżej sprawdza następujące warunki przed pozwoleniem na wydanie pudełka:
-
Aktualny numer bloku blockchaina Ergo (znany jako wysokość blockchaina) jest
większy niż określony termin -
Transakcja wydania musi być podpisana przez właściciela klucza tajnego
odpowiadającego kluczowi publicznemu ownerPk.
Pierwszy warunek zabrania komukolwiek wydawania pudełka przed tym, jak blockchain Ergo osiągnie daną wysokość. Ponieważ nowe bloki na blockchainie są wydobywane średnio co 2 minuty, korzystając z aktualnej
wysokości blockchaina, łatwo jest zdefiniować dowolny czas opóźnienia, jaki chcemy, na przykład 1 dzień, 1 tydzień lub 1 miesiąc. (tzn. (60 / 2) * 24 * 7 = 5040, co jest liczbą bloków na tydzień).
Teraz przejdziemy do szczegółowego omówienia, jak możemy wziąć ten kontrakt Freezera i zintegrować go z biblioteką Apkit, aby stworzyć aplikację konsolową FreezeCoin, aby każdy mógł zdecydować się na zamrożenie swoich monet, jeśli zechce. (Oczywiście, ten kontrakt/dApp nie jest w rzeczywistości użyteczny, jednak jest to skuteczny prosty przykład ilustrujący, jak działa ten stos technologiczny, abyś mógł samodzielnie budować użyteczne dApps w przyszłości.)
1. Rozwój aplikacji Java Ergo
Appkit ma na celu dostarczenie zestawu interfejsów, które można używać idiomatycznie
w Javie. Będziesz czuć się jak w domu, korzystając z Appkit, jeśli jesteś weteranem Javy.
Proszę postępować zgodnie z instrukcjami
konfiguracyjnymi dla GraalVM i
Appkit, jeśli chcesz odtworzyć poniższe przykłady.
Aby użyć Appkit w naszej implementacji Java FreezeCoin, musimy dodać
następującą zależność w pliku gradle
dependencies {
implementation("org.ergoplatform", "ergo-appkit_2.12", "3.1.0", "compile")
...
}
Ponadto w czasie wykonywania Appkit/nasza aplikacja musi połączyć się z węzłem Ergo za pomocą REST API. Często,
węzeł będzie działał lokalnie i będzie dostępny pod adresem http://localhost:9052/. To standardowy scenariusz dla każdego, kto skonfigurował pełny węzeł, postępując zgodnie z tym
przewodnikiem i korzysta z domyślnej konfiguracji.
Od teraz zakładamy, że skonfigurowałeś i uruchomiłeś swój węzeł Ergo, aby był dostępny do testowania aplikacji.
Następnie nasza aplikacja będzie musiała wiedzieć, jak połączyć się z naszym lokalnym działającym węzłem, oprócz innych różnych ustawień, aby działała poprawnie. Użyjemy pliku json z następującymi
parametrami konfiguracyjnymi, które nasza aplikacja FreezeCoin załaduje przy uruchomieniu.
{
"node": {
"nodeApi": {
"apiUrl": "http://localhost:9052/",
"apiKey": "wstaw tutaj swój tajny klucz api wygenerowany podczas konfiguracji węzła"
},
"wallet": {
"mnemonic": "klucz mnemoniczny użyty do zainicjowania lub przywrócenia portfela węzła",
"password": "hasło, które wybrałeś, aby chronić portfel",
"mnemonicPassword": "hasło, które wybrałeś, aby chronić mnemonikę"
},
"networkType": "TESTNET"
},
"parameters": {
"newBoxSpendingDelay": "30",
"ownerAddress": "3WzR39tWQ5cxxWWX6ys7wNdJKLijPeyaKgx72uqg9FJRBCdZPovL"
}
}
Tutaj apiKey to tajny klucz wymagany do uwierzytelnienia API, który można
uzyskać, jak opisano
tu.
Twój mnemonik to tajna fraza uzyskana podczas konfiguracji nowego
portfela.
Jak nasza aplikacja będzie działać, to użytkownik uruchomi ją z linii poleceń i poda jeden argument. Ten argument to ilość wartości (w NanoErgach), którą chce zamrozić/zablokować pod kontraktem Freezera, który napisaliśmy powyżej.
Naszym pierwszym krokiem dla aplikacji FreezeCoin będzie odczytanie pliku konfiguracyjnego json, który właśnie stworzyliśmy, i zaakceptowanie argumentu wiersza poleceń od użytkownika:
public static void main(String[] args) {
long amountToSend = Long.parseLong(args[0]); // dodatnia wartość w NanoErgach
ErgoToolConfig conf = ErgoToolConfig.load("freeze_coin_config.json");
// reszta kodu omówiona poniżej
...
}
Dzięki tym danym możemy teraz uzyskać opóźnienie wydania i adres właściciela, które zostały zdefiniowane w pliku konfiguracyjnym json.
int newBoxSpendingDelay = Integer.parseInt(conf.getParameters().get("newBoxSpendingDelay"));
Address ownerAddress = Address.create(conf.getParameters().get("ownerAddress"));
Następnie musimy połączyć się z działającym węzłem Ergo z naszej aplikacji Java, aby móc użyć danych, które właśnie przetworzyliśmy, i opublikować coś na łańcuchu. Robi się to poprzez stworzenie
instancji ErgoClient, która wykorzystuje nasze wcześniej zdefiniowane wartości dla naszego węzła z pliku konfiguracyjnego json.
ErgoNodeConfig nodeConf = conf.getNode();
ErgoClient ergoClient = RestApiErgoClient.create(nodeConf);
Teraz, gdy mamy instancję ErgoClient,
możemy wykonać dowolny blok kodu i mieć dostęp do aktualnego kontekstu blockchaina.
String txJson = ergoClient.execute((BlockchainContext ctx) -> {
// użyj ctx tutaj, aby stworzyć i podpisać nową transakcję
// następnie wyślij ją do węzła
});
Lambda przekazana do execute jest wywoływana, gdy aktualny kontekst blockchaina
jest ładowany z węzła Ergo. W tej lambdzie
umieścimy naszą logikę aplikacji.
Najpierw zaczynamy od kilku kroków pomocniczych.
// uzyskaj dostęp do portfela osadzonego w węźle Ergo
// (korzystając z portfela określonego za pomocą mnemoniki, którą umieściliśmy w freeze_coin_config.json)
ErgoWallet wallet = ctx.getWallet();
// oblicz całkowitą ilość NanoErgów, które musimy wysłać do nowego pudełka
// w tym opłaty za transakcje
long totalToSpend = amountToSend + Parameters.MinFee;
// poproś o niezużyte pudełka, które pokrywają wymaganą ilość NanoErgów z portfela
Optional<List<InputBox>> boxes = wallet.getUnspentBoxes(totalToSpend);
if (!boxes.isPresent())
throw new ErgoClientException(
"Nie wystarczająca ilość monet w określonym portfelu, aby zapłacić " + totalToSpend, null);
// stwórz "prover", który jest specjalnym obiektem, który będzie używany do podpisywania transakcji
// prover powinien być skonfigurowany z tajemnicami twojego portfela, które są niezbędne do generowania podpisów (tzw. dowodów)
ErgoProver prover = ctx.newProverBuilder()
.withMnemonic(
nodeConf.getWallet().getMnemonic(),
nodeConf.getWallet().getPassword())
.build();
Na tym etapie mamy wybrane pudełka wejściowe do naszej transakcji wydania, ale teraz musimy stworzyć pudełko wyjściowe z określoną amountToSend i zablokowane pod kontraktem Freezera.
// jedynym sposobem na stworzenie transakcji jest użycie budowniczego tx uzyskanego z kontekstu
// budowniczy używa kontekstu do uzyskania niezbędnych danych blockchaina.
UnsignedTransactionBuilder txB = ctx.newTxBuilder();
// stwórz nowe pudełko, używając nowego budowniczego uzyskanego z budowniczego transakcji
// w tym przypadku kompilujemy nowy ErgoContract z kodu ErgoScript Freezera
OutBox newBox = txB.outBoxBuilder()
.value(amountToPay)
.contract(ctx.compileContract(
ConstantsBuilder.create()
.item("freezeDeadline", ctx.getHeight() + newBoxSpendingDelay)
.item("ownerPk", ownerAddress.getPublicKey())
.build(),
"{ sigmaProp(HEIGHT > freezeDeadline) && ownerPk }"))
.build();
Zauważ, aby skompilować ErgoContract z kodu źródłowego skryptu Freezera, metoda compileContract
wymaga, abyśmy dostarczyli wartości dla nazwanych stałych, które są używane w skrypcie.
Jeśli nie używa się takich stałych, można przekazać ConstantsBuilder.empty().
W tym przypadku przekazujemy klucz publiczny nowego właściciela pudełka do miejsca ownerPk
w skrypcie. Aby powtórzyć z wcześniejszego, oznacza to, że pudełko może być wydane tylko przez właściciela
odpowiadającego klucza tajnego.
Następnie tworzymy niepodpisaną transakcję, używając wszystkich danych, które dotychczas zebraliśmy.
// przekaż budowniczemu transakcji, które pudełka zamierzamy wydać, które wyjścia
// powinny być stworzone, całkowite opłaty transakcyjne i adres, na który ma być wysłana reszta
UnsignedTransaction tx = txB.boxesToSpend(boxes.get())
.outputs(newBox)
.fee(Parameters.MinFee)
.sendChangeTo(prover.getP2PKAddress())
.build();
A na koniec:
- Użyj prover do podpisania zbudowanej transakcji
- W ten sposób uzyskaj instancję
SignedTransaction - Użyj kontekstu blockchaina, aby wysłać podpisaną transakcję do
węzła Ergo.
Wynikowy txId można użyć do odniesienia się do tej transakcji
później, jednak nie używamy go tutaj.
SignedTransaction signed = prover.sign(tx);
String txId = ctx.sendTransaction(signed);
return signed.toJson(true);
Jak mogłeś zauważyć, w naszym ostatnim kroku pokazujemy, że możliwe jest serializowanie podpisanej
transakcji do ciągu Json z włączonym ładnym formatowaniem. Zobacz pełny
kod źródłowy
przykładu, aby uzyskać więcej szczegółów i użyć go jako szablonu w swojej własnej
aplikacji.
Teraz, gdy cały kod jest gotowy, możemy uruchomić naszą aplikację FreezeCoin, wykonując następujące kroki
(przy założeniu, że jesteś w katalogu, w którym sklonowałeś
ergo-appkit-examples).
$ pwd
the/directory/you/cloned/ergo-appkit-examples
$ ./gradlew clean shadowJar
To złoży plik build/libs/appkit-examples-3.1.0-all.jar, który zawiera
naszą aplikację Java FreezeCoin i wszystkie jej zależności w jednym dużym jarze.
Zauważ, że ten krok musi być powtarzany po każdej zmianie w kodzie źródłowym Java naszej aplikacji.
Po stworzeniu naszej aplikacji możemy teraz użyć naszej aplikacji FreezeCoin:
$ java -cp build/libs/appkit-examples-3.1.0-all.jar \
org.ergoplatform.appkit.examples.FreezeCoin 1000000000
Otrzymasz coś w stylu tego wyjścia w konsoli.
I w ten sposób twoja transakcja została zaakceptowana przez węzeł Ergo i rozesłana do sieci, gdzie będzie czekać w puli transakcji na dodanie do bloku. Gdy górnik wybierze ją i doda do bloku, twoje monety będą oficjalnie "zamrożone" w nowo utworzonym pudełku na podstawie wartości, które podałeś aplikacji FreezeCoin.
Przykład zakłada, że węzeł Ergo (i osadzony portfel) jest własnością użytkownika
FreezeCoin. Jednak nie jest to ściśle wymagane, a interfejsy Appkit
mogą być używane do tworzenia i wysyłania nowych transakcji przy użyciu dowolnych publicznych węzłów Ergo.
2. Aplikacje Ergo o niskim zużyciu zasobów i szybkim uruchamianiu
Jak być może wiesz, używanie Javy do krótkoterminowych procesów ma wiele wad.
Aplikacje mają tendencję do cierpienia z powodu długich czasów uruchamiania i stosunkowo wysokiego zużycia pamięci.
Uruchommy FreezeCoin, używając polecenia time, aby
uzyskać rzeczywisty (czas rzeczywisty) czas, jaki zajmuje całemu programowi uruchomienie od
początku do końca. Używamy flagi -l, aby również wydrukować zużycie pamięci.
$ /usr/bin/time -l java -cp build/libs/appkit-examples-3.1.0-all.jar \
org.ergoplatform.appkit.examples.FreezeCoin 1000000000
...
4.97 real 8.41 user 0.69 sys
513703936 maksymalny rozmiar zestawu rezydentów
0 średni rozmiar pamięci współdzielonej
0 średni rozmiar danych niepodzielonych
0 średni rozmiar stosu niepodzielonego
125010 odzyskiwanie stron
1216 błędy stron
0 wymiany
0 operacje wejścia bloków
0 operacje wyjścia bloków
13 wysłane wiadomości
86 odebrane wiadomości
1 odebrane sygnały
2384 dobrowolne przełączania kontekstu
17409 przymusowe przełączania kontekstu
Jak widać powyżej, ta mała aplikacja zajęła 2 równoległe wątki prawie 4
sekundy na uruchomienie. Większość tego czasu można przypisać uruchomieniu JVM i
działającemu w tle kompilatorowi JIT. To dość słaba wydajność, a wiemy, że możemy zrobić znacznie lepiej.
Na szczęście GraalVM zapewnia nam idealne rozwiązanie.
Możemy rozwiązać ten inherentny problem z JVM, kompilując kod Java
ahead-of-time do natywnego obrazu wykonywalnego za pomocą GraalVM. To pomija potrzebę korzystania z kompilatora Java just-in-time
w czasie wykonywania.
Doświadczenie dla nas (dewelopera korzystającego z GraalVM) jest dość podobne do konwencjonalnego kompilatora, takiego jak gcc. Zauważ,
możemy najpierw musieć uruchomić ./gradlew clean shadowJar.
$ ./gradlew clean shadowJar
$ native-image --no-server \
-cp build/libs/appkit-examples-3.1.0-all.jar\
--report-unsupported-elements-at-runtime\
--no-fallback -H:+TraceClassInitialization -H:+ReportExceptionStackTraces\
-H:+AddAllCharsets -H:+AllowVMInspection -H:-RuntimeAssertions\
--allow-incomplete-classpath \
--enable-url-protocols=http,https org.ergoplatform.appkit.examples.FreezeCoin freezecoin
[freezecoin:3133] classlist: 35,217.78 ms
[freezecoin:3133] (cap): 6,063.07 ms
[freezecoin:3133] setup: 8,268.99 ms
[freezecoin:3133] (typeflow): 60,238.25 ms
[freezecoin:3133] (objects): 33,009.06 ms
[freezecoin:3133] (features): 4,796.86 ms
[freezecoin:3133] analysis: 102,876.01 ms
[freezecoin:3133] (clinit): 11,642.43 ms
[freezecoin:3133] universe: 13,718.96 ms
[freezecoin:3133] (parse): 5,053.18 ms
[freezecoin:3133] (inline): 18,317.24 ms
[freezecoin:3133] (compile): 44,806.82 ms
[freezecoin:3133] compile: 72,288.24 ms
[freezecoin:3133] image: 7,955.29 ms
[freezecoin:3133] write: 2,872.25 ms
[freezecoin:3133] [total]: 243,813.30 ms
Prosta komenda powyżej produkuje kompletny natywny plik wykonywalny o nazwie freezecoin.
Aby podkreślić, ten plik wykonywalny nie jest jedynie uruchamiaczem dla JVM. W rzeczywistości nie łączy się z JVM ani nie pakuje
także JVM w żaden sposób. native-image kompiluje kod FreezeCoin, a także wszelkie
biblioteki Java, na których polega, aż do prostego kodu maszynowego.
Jeśli spojrzymy na biblioteki, które wykorzystuje freezecoin, możemy zobaczyć, że używa tylko standardowych bibliotek systemowych. W ten sposób możemy przenieść tylko ten jeden plik wykonywalny na inny system,
który nie ma zainstalowanego JVM, a on tam będzie działać bez problemu.
$ otool -L freezecoin # ldd freezecoin na Linuxie
freezecoin:
/usr/lib/libSystem.B.dylib (wersja zgodności 1.0.0, aktualna wersja 1252.50.4)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (wersja zgodności 150.0.0, aktualna wersja 1455.12.0)
/usr/lib/libz.1.dylib (wersja zgodności 1.0.0, aktualna wersja 1.2.11)
Jeśli zmierzymy ten nowy plik wykonywalny freezecoin, możemy zobaczyć, że uruchamia się on około 8 razy szybciej i używa
około 6 razy mniej pamięci. Co to oznacza, to to, że nie odczuwasz tego wyraźnego opóźnienia, które zawsze występuje podczas uruchamiania
krótkoterminowego programu z JVM.
$ DYLD_LIBRARY_PATH=$GRAAL_HOME/jre/lib /usr/bin/time -l ./freezecoin 1800000000
0.43 real 0.15 user 0.03 sys
81289216 maksymalny rozmiar zestawu rezydentów
0 średni rozmiar pamięci współdzielonej
0 średni rozmiar danych niepodzielonych
0 średni rozmiar stosu niepodzielonego
20079 odzyskiwanie stron
0 błędy stron
0 wymiany
0 operacje wejścia bloków
0 operacje wyjścia bloków
13 wysłane wiadomości
86 odebrane wiadomości
0 odebrane sygnały
11 dobrowolne przełączania kontekstu
138 przymusowe przełączania kontekstu
To tylko jedna z wielkich zalet GraalVM, z której możemy skorzystać dzięki Appkit.
3. Rozwój aplikacji Ergo w JavaScript, Pythonie, Ruby
GraalVM wspiera tzw. programowanie wielojęzyczne, w którym różne komponenty
aplikacji mogą być rozwijane przy użyciu najbardziej odpowiedniego języka, a następnie
bezproblemowo łączyć się w czasie wykonywania. W ten sposób unikalna biblioteka napisana na przykład w
Javie może być używana w aplikacji node.js napisanej w JavaScript.
Aby wspierać programowanie wielojęzyczne, platforma GraalVM ma swoje własne wysokowydajne
implementacje popularnych języków. Zamierzamy skorzystać z tego w
naszym projekcie przykładowym FreezeCoin, aby pokazać, jak łatwo jest używać preferowanego języka.
Przed uruchomieniem poniższych przykładów (w JavaScript, Pythonie i Ruby) upewnij się, że masz
wersję Java FreezeCoin działającą lokalnie, aby upewnić się, że wszystko jest poprawnie skonfigurowane.
JavaScript
GraalVM może uruchamiać JavaScript i
Node.js
aplikacje od ręki. Jest zgodny z specyfikacją ECMAScript 2019
.
Dodatkowo, uruchamiacze js i node akceptują specjalne opcje wiersza poleceń --jvm i --polyglot,
które pozwalają skryptom JS uzyskiwać dostęp do obiektów i klas Java.
Biorąc to pod uwagę, implementacja JS FreezeCoin może być łatwo napisana przy użyciu interfejsu API Appkit.
Proszę zobaczyć pełny kod źródłowy implementacji FreezeCoin JS
po szczegóły.
Następująca komenda używa uruchamiacza node, aby wykonać skrypt FreezeCoin.js.
$ node --jvm --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
js-examples/FreezeCoin.js 1000000000
Zauważ, że ścieżki w poleceniu są względne do katalogu głównego
projektu ergo-appkit-examples.
Python
GraalVM może uruchamiać skrypty Pythona, chociaż
implementacja Pythona jest nadal eksperymentalna (zobacz także
sekcję zgodności
po szczegóły).
Przykład Pythona
FreezeCoin
można wykonać za pomocą następującej komendy
$ graalpython --jvm --polyglot --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
python-examples/FreezeCoin.py 1900000000
Ruby
GraalVM może uruchamiać skrypty Ruby przy użyciu
implementacji TruffleRuby, która jest jednak nadal eksperymentalna (zobacz także
sekcję zgodności
po szczegóły).
TruffleRuby ma na celu pełną zgodność z standardową implementacją Ruby, MRI, wersja 2.6.2.
Przykład Ruby
FreezeCoin
można wykonać za pomocą następującej komendy
$ truffleruby --polyglot --jvm --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
ruby-examples/FreezeCoin.rb 1900000000
4. Natywne biblioteki współdzielone Ergo
Kolejną wielką zaletą GraalVM jest to, że możemy kompilować klasy Java do natywnej biblioteki współdzielonej zamiast pliku wykonywalnego.
Aby to zrobić, deklarujemy jedną lub więcej metod statycznych jako @CEntryPoint.
public class FreezeCoin {
...
/**
* Punkt wejścia wywoływalny z C, który opakowuje {@link FreezeCoin#sendTx}
*/
@CEntryPoint(name = "sendTx")
public static void sendTxEntryPoint(
IsolateThread thread,
SignedWord amountToSendW,
CCharPointer configFileNameC,
CCharPointer resBuffer, UnsignedWord bufferSize) throws FileNotFoundException {
long amountToSend = amountToSendW.rawValue();
// Konwertuj ciągi C na docelowe ciągi Java.
String configFileName = CTypeConversion.toJavaString(configFileNameC);
String txJson = sendTx(amountToSend, configFileName);
// umieść wynikowy ciąg w podanym buforze
CTypeConversion.toCString(txJson, resBuffer, bufferSize);
}
...
}
Możemy następnie skompilować do biblioteki współdzielonej i automatycznie wygenerowanego pliku nagłówkowego. Zauważ użycie opcji --shared.
$ native-image --no-server \
-cp build/libs/appkit-examples-3.1.0-all.jar\
--report-unsupported-elements-at-runtime\
--no-fallback -H:+TraceClassInitialization -H:+ReportExceptionStackTraces\
-H:+AddAllCharsets -H:+AllowVMInspection -H:-RuntimeAssertions\
--allow-incomplete-classpath \
--enable-url-protocols=http,https
--shared -H:Name=libfreezecoin -H:Path=c-examples
$ otool -L c-examples/libfreezecoin.dylib
c-examples/libfreezecoin.dylib:
.../c-examples/libfreezecoin.dylib (wersja zgodności 0.0.0, aktualna wersja 0.0.0)
/usr/lib/libSystem.B.dylib (wersja zgodności 1.0.0, aktualna wersja 1252.50.4)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (wersja zgodności 150.0.0, aktualna wersja 1455.12.0)
/usr/lib/libz.1.dylib (wersja zgodności 1.0.0, aktualna wersja 1.2.11)
Teraz mamy możliwość napisania programu C
który używa tej biblioteki.
Interfejs do naszej natywnej biblioteki ma trochę
boilerplate (ponieważ VM musi zarządzać stertą, wątkami, zbieraczem śmieci
i innymi), dlatego musimy stworzyć instancję i dostarczyć ją
naszemu głównemu wątkowi.
#include <stdlib.h>
#include <stdio.h>
#include <libfreezecoin.h>
int main(int argc, char **argv) {
graal_isolate_t *isolate = NULL;
graal_isolatethread_t *thread = NULL;
if (graal_create_isolate(NULL, &isolate, &thread) != 0) {
fprintf(stderr, "błąd graal_create_isolate\n");
return 1;
}
char * configFileName = "freeze_coin_config.json";
// uzyskaj amountToSend z argumentów cmd i wywołaj tworzenie transakcji
long amountToSend = atol(argv[1]);
char result[1024 * 16];
sendTx(thread, amountToSend, configFileName, result, sizeof(result));
// wydrukuj zserializowany wynik
printf("%s\n", result);
if (graal_detach_thread(thread) != 0) {
fprintf(stderr, "błąd graal_detach_thread\n");
return 1;
}
return 0;
}
Możemy to skompilować za pomocą naszych standardowych narzędzi systemowych i łatwo uruchomić nasz plik wykonywalny (ustaw LD_LIBRARY_PATH=. na Linuxie).
$ clang -Ic-examples -Lc-examples -lfreezecoin c-examples/freezecoin.c -o call_freezecoin
$ otool -L call_freezecoin
$ DYLD_LIBRARY_PATH=$GRAAL_HOME/jre/lib ./call_freezecoin 1000000000
5. Debugowanie aplikacji Ergo w wielu językach
Możesz debugować JS, Pythona i Ruby w IntelliJ, ale jeśli z jakiegoś powodu to
nie działa dla ciebie lub nie pasuje do twojego preferowanego edytora, GraalVM oferuje inną opcję.
Wszystkie języki GraalVM (z wyjątkiem Javy) są implementowane przy użyciu wspólnego
frameworka Truffle.
Truffle pozwala na narzędzia takie jak debugery, które można zaimplementować raz i udostępnić
wszystkim obsługiwanym językom.
W związku z tym możemy uruchomić nasz program z flagą --inspect, co da nam link do
otwarcia w Chrome i zatrzyma program w debuggerze.
$ ruby --polyglot --jvm --inspect --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
ruby-examples/FreezeCoin.rb 1900000000
Debugger nasłuchuje na porcie 9229.
Aby rozpocząć debugowanie, otwórz następujący adres URL w Chrome:
chrome-devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/30c7da1e-7558a47d09b
...
Stąd możemy ustawiać punkty przerwania i kontynuować wykonanie. Gdy zatrzyma się, zobaczymy
wartości zmiennych, możemy kontynuować aż do następnego punktu przerwania i robić wszystko, co oczekujemy od debuggerów.

Wnioski
I z tym wszystkim powiedzianym i zrobionym, widzimy, jak łatwo jest używać Appkit do
developowania aplikacji Ergo. Appkit opiera się na tych samych dokładnych podstawowych bibliotekach, które
zostały użyte do implementacji protokołu konsensusu Ergo. Te biblioteki obejmują
kompilator ErgoScript, kryptografię, interpreter kodu bajtowego, serializatory danych
i inne podstawowe komponenty. Korzystając z GraalVM, możemy ponownie wykorzystać te sprawdzone
i przetestowane komponenty w różnych kontekstach aplikacji bez jakichkolwiek modyfikacji
lub przepisywania ich samodzielnie.
Niezależnie od tego, czy używasz Javy, JavaScriptu, Pythona czy Ruby, możesz skorzystać
z Appkit z GraalVM, aby znacznie uprościć proces
interakcji z blockchainem Ergo, tworząc natywnie działające (d)Apps.
Bądź na bieżąco. W przyszłych postach przedstawimy ci inne interesujące potencjalne
aplikacje zasilane przez Appkit.
Odnośniki
Share post
13 sierpnia 2025
12 maja 2025






