Wcześniej, kiedy dołączyliśmy do Linux Foundation aby pracować nad LF Edge i przejść w stronę otwartej współpracy ogłosiliśmy również, że od dłuższego czasu pracujemy nad wewnętrznym mostem do Hyperledger Fabric.
Widzieliśmy, że Hyperledger i cały ekosystem Hyperledger wykonali ogromną pracę, rozwijając stan technologii rozproszonej księgi rachunkowej (DLT) udostępnianej za zgodą (permissioned).
Możliwości danych i odpowiednie narzędzia wychodzące z ekosystemu były pod wieloma względami ekscytujące i postępowe. W IOTA pracujemy nad poprawą stanu DLT udostępnianego każdemu (permissionless), z elastycznymi możliwościami dotyczącymi zarówno transferu danych, jak i wartości.
Nie oznacza to jednak, że nie widzimy wartości także w systemach permissioned. Aby jeszcze bardziej umożliwić wzajemny wzrost i wartość jaką mogą zapewnić zarówno systemy permissioned, jak i systemy permissionless, przechodzimy dziś naprzód dzięki oficjalnemu otwartemu dostępowi do naszego mostu z Hyperledger Fabric.
Most ten umożliwi bezpośrednią integrację zarówno funkcji Hyperledger Fabric jak i IOTA, działając jako łącze IOTA. Dzięki temu, Tangle może działać jako tkanka łączna między systemami permissioned opartymi na technologii Hyperledger Fabric, a także umożliwia bardziej płynne dzielenie się danymi i sprawdzanie poprawności za pomocą silosowych systemów permissionless.
W tym momencie rozważamy Hyperledger Fabric DLT – w którym wszystkie dane są początkowo przechowywane i zarządzane – jako główne źródło prawdy.
Każde wykonanie inteligentnej umowy (smart contract) może teraz wyzwalać żądanie do IOTA Tangle przy użyciu dostarczonego oprogramowania. Proces ten pozwala przechowywać/aktualizować wyniki wykonania inteligentnej umowy Hyperledger Fabric na Tangle i wykonywać płatności między posiadaczami portfela IOTA.
Możliwe jest również odczytywanie danych z Tangle i wyzwalanie wykonania inteligentnej umowy Hyperledger Fabric na podstawie pobranych danych transakcji lub potwierdzenia płatności.
Przykłady kodu przedstawione poniżej pokazują, jak można wdrożyć wiele scenariuszy integracji IOTA w powszechnym projekcie łańcucha dostaw opartym na systemie Hyperledger Fabric.
Inteligentne umowy w Hyperledger Fabric można pisać w kilku językach programowania. Dostarczyliśmy konektory IOTA dla dwóch najpopularniejszych: Go i JavaScript.
W tym wpisie na blogu nie zajmiemy się szczegółami architektury Hyperledger Fabric oraz jej konfiguracją. Zakładamy, że znasz już typowy projekt Hyperledger Fabric i najprawdopodobniej jeden taki projekt masz uruchomiony.
Możesz pobrać pliki źródłowe Hyperledger Fabric Chaincode dla połączenia z IOTA Tangle, z tego publicznego repozytorium GitHub.
Jak zintegrować połączenie z IOTA
Zaczniemy od prostego pliku kodu łańcucha odpowiedniego dla projektu łańcucha dostaw i dodamy kilka złączy IOTA jeden po drugim z krótkim opisem użytkowania.
Zwykły kod łańcuchowy Hyperledger Fabric napisany w Go ma przestrzeń nazw, którą można zdefiniować jako plik docker-compose.yml w woluminach:

W naszym przypadku folder łańcucha jest mapowany na przestrzeń nazw github.com. Wszystkie pakiety zewnętrzne, w tym złącze IOTA muszą zostać zaimportowane przy użyciu tej samej przestrzeni nazw.
Zaczynamy od dodania kodu złącza IOTA do folderu chaincode.

Ponadto musisz dodać 3 inne pakiety uzupełniające.
Możesz to zrobić, dodając instrukcję do skryptu powłoki, który instaluje i uruchamia instancję Hyperledger, lub ręcznie pobierając i kopiując projekty do folderu chaincode.
Aby dodać instrukcje do skryptu powłoki, dodaj następujące trzy wiersze przed poleceniem „chaincode install”

Zapewni to pobranie wymaganych pakietów i umieszczenie ich w folderze chaincode, zmapowanym jako github.com.
W zależności od wersji Go ostatnie polecenie pobierania biblioteki iota.go może się nie powieść. W takim przypadku możesz pobrać go ręcznie i umieścić w folderze chaincode.

Następnie, dodaj import biblioteki konektora IOTA do listy importów pliku chaincode.go. Uwaga: przestrzeń nazw gibhub.com pochodzi z nazwy pakietu iota. Jeśli Twoja organizacja używa innej przestrzeni nazw, dostosuj ją odpowiednio.

Cyfrowy bliźniak
Chaincode Hyperledger zawiera funkcję o nazwie initLedger, w której można zdefiniować początkową strukturę księgi i przechowywać dane jako pary klucz/wartość. W przypadku typów złożonych, zwykle używasz struktur do opisywania pól obiektowych.
W naszym przykładzie, początkowa struktura księgi składa się z wielu definicji kontenerów, przy czym każdy kontener zawiera pole Holder między wieloma innymi.

Po zdefiniowaniu struktury jest ona zapisywana w księdze jeden po drugim.

Jest to jeden z możliwych sposobów przechowywania danych w księdze. Nie twierdzimy, że opracowaliśmy najlepszą możliwą opcję.
Dodamy tutaj złącze IOTA, aby zapewnić, że cyfrowy bliźniak jest przechowywany w Tangle w strumieniach wiadomości MAM. Stworzymy osobny strumień wiadomości dla każdego kontenera, w którym będą śledzone wszystkie zmiany danych kontenera, lokalizacji, posiadacza itp.
Najpierw, zdefiniuj strukturę strumienia IOTA MAM. Powinien on zawierać losowo generowany Seed, obiekt MamState, adres Root do pobierania danych, tryb strumieniowy i sideKey (klucz szyfrowania).

Następnie, zdefiniuj tryb i klucz szyfrowania dla każdego zasobu który dostanie cyfrowego bliźniaka w Tangle.
Możesz użyć jednego z następujących trybów: „public”, „private”, „restricted”.
SideKey (klucz szyfrowania) jest wymagany tylko w trybie „restricted”. W przeciwnym razie może pozostać pustym ciągiem.
Zapewniamy dwie funkcje pomocnicze dla sideKey. Obie funkcje są dostępne z przestrzeni nazw iota:
- iota.GenerateRandomSeedString(length) wygeneruje losowy ciąg o podanej długości. Może być używany jako klucz początkowy lub klucz szyfrujący.
- iota.PadSideKey() automatycznie dostosuje długość skrótu klawisza do 81 znaków.
Jeśli nie chcesz definiować własnych wartości dla mode i sideKey, możesz użyć wartości domyślnych iota.MamMode i iota.MamSideKey, które możesz sprawdzać i modyfikować w pliku chaincode/iota/config.go
Następnie, możesz wywołać funkcję iota.PublishAndReturnState(), która opublikuje ładunek wiadomości jako nowy kanał MAM. Ta funkcja zwraca wartości mamState, root i seed.
MamState i seed są potrzebne do dalszych dołączeń do tego samego kanału. Wartość root służy do odczytu danych z kanału.
Wartości te muszą być przechowywane w księdze głównej i przekazywane każdemu z partnerów organizacji.
Jeśli nie chcesz w przyszłości dodawać nowych wiadomości do tego samego kanału, możesz zamiast tego wywołać funkcję iota.Publish(), która nie zwróci MamState.
iota.PublishAndReturnState() wymaga następujących parametrów:
- Ładunek wiadomości (string)
- Istniejąca flaga strumienia MAM (bool)
- Istniejąca wartość początkowa (string)
- Istniejąca wartość MamState (string)
- Mode (string)
- sideKey (string)
Jeśli utworzysz nowy strumień MAM, ustaw wartości dla istniejącego strumienia MAM, seed i mamState na false, “”, “”
Po opublikowaniu wiadomości nadszedł czas, aby zachować wartości w księdze. Utwórz nowy obiekt typu IotaPayload i umieść go w księdze, podobnie jak tworzysz rekordy dla zasobów kontenera.
Pamiętaj, że zalecamy dodanie przedrostka, takiego jak „IOTA_” przed identyfikatorem zasobu.
APIstub.PutState(“IOTA_” + strconv.Itoa(i+1), iotaPayloadAsBytes)

Jeśli Twoja inteligentna umowa zawiera funkcję dodawania nowych rekordów do księgi, zaktualizuj tę funkcję, dodając do niej kod złącza IOTA.
Należy pamiętać, że identyfikator nowego zasobu jest używany dla nowego obiektu IOTA
APIstub.PutState(“IOTA_” + args[0], iotaPayloadAsBytes)

Podobnie, jeśli Twoja inteligentna umowa zawiera funkcję modyfikującą istniejące rekordy, zaktualizuj tę funkcję, dodając do niej również kod złącza IOTA.
Należy pamiętać, że w tym przypadku dołączamy zmodyfikowane dane zasobu do istniejącego strumienia MAM tego zasobu. Dlatego pobieramy iotaPayload dla określonych zasobów z księgi i przekazujemy te informacje do funkcji iota.PublishAndReturnState(), wraz z istniejącą flagą strumienia MAM ustawioną na true.
Należy również pamiętać, że w tym momencie nie można zmienić trybu i klucza szyfrowania istniejącego strumienia MAM. Proszę użyć istniejących wartości zapisanych w księdze.
Po dodaniu nowej wiadomości do istniejącego strumienia, nowy MamState powinien zastąpić poprzedni stan w księdze. Wszystkie pozostałe wartości powinny pozostać takie same jak poprzednio.

Jeśli twoja inteligentna umowa zawiera funkcję zapytania o konkretny rekord z księgi, możesz również pobrać i zwrócić stan zapisany w Tangle. Aby wykonać zapytanie z Tangle, możesz użyć następującej funkcji dostępnej z kodu złącza IOTA:
iota.Fetch(root, mode, sideKey)
Należy pamiętać, że identyfikator zasobu służy do pobierania odpowiedniego obiektu IOTA z księgi głównej.
iotaPayloadAsBytes, _ := APIstub.GetState(“IOTA_” + args[0])

Pobrane wiadomości są zwracane jako tablica ciągów. Jeśli chcesz połączyć je razem w jeden ciąg i dodać do obiektu wyjściowego, musisz również zaimportować pakiet Go „strings”.
Ponadto, jeśli chcesz wyprowadzać wartości MamState, aby móc wykonywać inne działania w interfejsie użytkownika, takie jak potwierdzanie i porównywanie danych z księgi z danymi przechowywanymi w Tangle, możesz dodać obiekt MamState do wyniku.

Wysyłanie płatności
Projekty łańcucha dostaw mogą skorzystać z wbudowanego rozwiązania płatniczego, w którym płatności za niektóre usługi i towary mogą być przesyłane między uczestnikami łańcucha dostaw.
Jednym z możliwych przypadków użycia może być wysyłanie przez sprzedawców detalicznych lub konsumentów końcowych płatności do producentów, logistyki i dostawców usług związanych z zamówionymi aktywami.
Ponieważ żaden z projektów Hyperledger nie obsługuje kryptowaluty ani żadnego innego rodzaju płatności, łącznika IOTA można używać do dokonywania płatności bez opłat między uczestnikami w momencie, gdy inteligentna umowa potwierdza udaną transakcję.
Aby wysłać płatność za pomocą portfela IOTA, musisz przechowywać seed portfela i keyIndex w księdze rachunkowej. Seed jest używany do inicjowania transakcji, a keyIndex jest specyficzny dla implementacji IOTA i reprezentuje indeks bieżącego adresu portfela, który przechowuje tokeny.
Po każdej transakcji płatności wychodzącej pozostałe tokeny są przenoszone na następny adres w celu uniknięcia podwójnych wydatków. Indeks nowego adresu (zwany remainderAddress) powinien być przechowywany w księdze i wykorzystywany do następnej płatności wychodzącej. Płatności przychodzące nie powodują zmiany adresu ani indeksu.
W tym przykładzie utrzymamy tylko jeden portfel dla płatności wychodzących. Ten portfel zostanie przypisany sprzedawcy detalicznemu, który jest konsumentem końcowym zasobu w tym projekcie łańcucha dostaw.
Płatność będzie wysyłana do poprzedniego posiadacza aktywów za każdym razem, gdy zmieni się posiadacz, co wskazuje na przesunięcie aktywów w kierunku konsumenta końcowego. Innymi słowy, gdy producent przygotuje kontener do wysyłki i przekaże go spedytorowi, sprzedawca zapłaci producentowi tokenami IOTA. Następnie, gdy spedytor dostarczy kontener do następnego miejsca docelowego, sprzedawca prześle tokeny IOTA, aby zapłacić za tę usługę.
Wszyscy potencjalni uczestnicy tego przykładowego projektu łańcucha dostaw są określani przy inicjalizacji księgi głównej. Dla uproszczenia zakładamy, że jest tylko jeden uczestnik z rolą „Producent”, „Nadawca” itd.

Zaczniemy od definicji struktury obiektu portfela.

Ta struktura zawiera seed i keyIndex, jak opisano powyżej. Ponadto zawiera także rzeczywisty adres, na którym obecnie przechowywane są tokeny. Możesz wykonać kontrolę salda, aby zapewnić wystarczającą równowagę portfela. Wprowadź swój adres portfela na tej stronie, aby sprawdzić bieżące saldo.
Następnie, rozszerzymy istniejącą strukturę uczestnika, dodając do niej część IotaWallet

Następnie, wygenerujemy nowy pusty portfel i dodamy informacje o portfelu do każdego rekordu uczestnika.
Aby wygenerować nowy portfel, możesz użyć funkcji ze złącza IOTA:
walletAddress, walletSeed := iota.CreateWallet()

Ponieważ generujemy nowy portfel dla każdego rekordu, ustawiamy wartość keyIndex na 0. Jeśli masz zamiar korzystać z istniejących portfeli, odpowiednio dostosuj wartości keyIndex.
Wygenerowane portfele są puste i obecnie mogą odbierać tylko tokeny IOTA.
Aby wysyłać tokeny, musisz posiadać co najmniej jeden portfel finansowany z tokenami IOTA.
Dane twojego portfelapowinny być przechowywane w księdze.
Możesz podać dane portfela po inicjalizacji księgi lub możesz zmodyfikować wartości w pliku konfiguracyjnym w pliku chaincode/iota/config.go

Aby przechowywać portfel w księdze, zaktualizuj funkcję initLedger(), dodając następujący kod. Można zastąpić wartości dla iota.DefaultWalletSeed i iota.DefaultWalletKeyIndex odpowiednimi wartościami portfela.

Po skonfigurowaniu portfeli możemy dodać funkcję wykonywania płatności. Składa się z 3 prostych kroków:
- Zidentyfikuj funkcję w inteligentnej umowie, która powinna uruchomić płatność.
- Zidentyfikuj odbiorcę płatności. Pobierz adres portfela odbiorcy.
- Zidentyfikuj nadawcę płatności. Pobierz seed portfela i keyIndex nadawcy. Wykonaj transfer tokena, następnie zaktualizuj keyIndex do nowej wartości i zapisz go w księdze.
W naszym przykładzie dokonamy płatności po zmianie właściciela aktywów. Tak więc funkcja wyzwalająca płatności o nazwie changeContainerHolder(). Odbiorca płatności jest poprzednim posiadaczem kontenera. Dlatego musimy zachować wartość posiadacza przed zmianą, aby móc pobrać odpowiednie dane portfela z księgi.
Na poniższym zrzucie ekranu widać wymagane aktualizacje funkcji. Dane kontenera są pobierane na podstawie podanego identyfikatora. Przed ponownym przypisaniem posiadacza przechowujemy oryginalną wartość posiadacza. Później przeszukujemy księgę w celu uzyskania adresu portfela oryginalnego posiadacza kontenera.

W kroku 3 poprosimy o dane portfela IOTA sprzedawcy. Następnie uruchomimy następującą funkcję i prześlemy wartości seed i keyIndex nadawcy i wartość adresu odbiorcy.
iota.TransferTokens(seed, keyIndex, address)
Po wykonaniu tej czynności wystarczy zaktualizować keyIndex do nowej wartości i zapisać go w księdze głównej.

Przekazanie tokena zwykle wymaga kilku sekund w celu potwierdzenia. Nie próbuj uruchamiać wielu przelewów z tego samego portfela w bardzo krótkim czasie (mniej niż 10 sekund), ponieważ spowoduje to błąd „Nieprawidłowe saldo”, a indeks klucza portfela należy ręcznie zresetować do poprzedniej wartości.
Jak zawsze możesz sprawdzić status transferu tokenów na tej stronie, wpisując adres portfela.
Po otwartym źródle oprogramowania IOTA Connector będziemy udostępniać możliwości jako Hyperledger Bridge do Linux Foundation. W chwili obecnej współpracujemy z Linux Foundation, aby zapewnić, że kod zostanie wprowadzony do projektu, który będzie najbardziej odpowiedni i postaramy się sfinalizować tę decyzję w nadchodzących tygodniach.
Zasoby
- Kod źródłowy IOTA Connector można pobrać z tego repozytorium GitHub typu open source.
- Dodatkową bibliotekę iota.go, która musi znajdować się w tym samym folderze z chaincode, można pobrać z tego repozytorium GitHub typu open source.
- Projekt demonstracyjny wykorzystany do zaprezentowania integracji IOTA Connector ma charakter open source i można go znaleźć w tym repozytorium GitHub.
Zachęcamy do odwiedzenia naszego oficjalnego serwera Discord – każdy wymieniony tutaj projekt ma kanał (lub więcej) do dyskusji z twórcami!
Obserwuj nas na Twitterze, aby śledzić wszystkie najnowsze wiadomości: https://twitter.com/iotatoken
Powyższy tekst jest tłumaczeniem postu z języka angielskiego który oryginalnie ukazał pod tym adresem.