OdpornoÅÄ na bÅÄdy bizantyjskie w systemach peer-to-peer - Instytut ...
OdpornoÅÄ na bÅÄdy bizantyjskie w systemach peer-to-peer - Instytut ...
OdpornoÅÄ na bÅÄdy bizantyjskie w systemach peer-to-peer - Instytut ...
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Politechnika Warszawska<br />
Wydział Elektroniki i Technik Informacyjnych<br />
Praca Dyplomowa Magisterska<br />
Odporność <strong>na</strong> błędy <strong>bizantyjskie</strong> w <strong>systemach</strong><br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Łukasz Walkiewicz<br />
praca pod kierunkiem dr inż. Tomasza Jorda<strong>na</strong> Kruka<br />
<strong>Instytut</strong> Au<strong>to</strong>matyki i Informatyki S<strong>to</strong>sowanej<br />
Warszawa 2005
Spis treści<br />
1 Wprowadzenie 5<br />
1.1 Zawar<strong>to</strong>ść poszczególnych rozdziałów . . . . . . . . . . . . . . . 6<br />
1.2 Geneza systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> . . . . . . . . . . . . . . . . . . . 7<br />
1.3 Zagadnienia bezpieczeństwa . . . . . . . . . . . . . . . . . . . . 8<br />
1.4 Zas<strong>to</strong>sowania sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> . . . . . . . . . . . . . . . . . . 10<br />
1.4.1 Współdzielenie plików . . . . . . . . . . . . . . . . . . . 11<br />
1.4.2 Anonimowe połączenia i trasowanie cebulkowe . . . . . 12<br />
1.4.3 Maskowanie usługi . . . . . . . . . . . . . . . . . . . . . 14<br />
2 Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 17<br />
2.1 Nieustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> . . . . . . . . . . . . 20<br />
2.2 Ustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> . . . . . . . . . . . . . 21<br />
2.2.1 Przestrzeń identyfika<strong>to</strong>rów . . . . . . . . . . . . . . . . . 22<br />
2.2.2 Trasowanie przedrostkowe . . . . . . . . . . . . . . . . . 24<br />
2.2.3 Rozproszone tablice z kodowaniem mieszającym . . . . . 25<br />
2.3 Architektura systemów Chord i Pastry . . . . . . . . . . . . . . . 27<br />
2.3.1 Algorytm routingu . . . . . . . . . . . . . . . . . . . . . 28<br />
2.3.2 Przyłączanie do systemu . . . . . . . . . . . . . . . . . . 29<br />
2.4 Bezpieczeństwo w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> . . . . . . . . . . . . . 30<br />
2.4.1 Klasyczne problemy bezpieczeństwa . . . . . . . . . . . 31<br />
2.4.2 Nadawanie identyfika<strong>to</strong>rów . . . . . . . . . . . . . . . . 32<br />
2.4.3 Przesyłanie komunikatów . . . . . . . . . . . . . . . . . 33<br />
2.4.4 Masowe przyłączanie i odłączanie . . . . . . . . . . . . . 33<br />
3 Bezpieczne <strong>bizantyjskie</strong> uzgadnianie 35<br />
3.1 Problem bizantyjskich generałów . . . . . . . . . . . . . . . . . 36<br />
3.2 Replikacja z uwzględnieniem błędów bizantyjskich . . . . . . . . 39<br />
3.3 Algorytm BFT . . . . . . . . . . . . . . . . . . . . . . . . . . . 40<br />
3.3.1 Założenia algorytmu BFT . . . . . . . . . . . . . . . . . 41<br />
3.3.2 Działanie algorytmu BFT . . . . . . . . . . . . . . . . . 42<br />
3.3.3 Optymalizacje zas<strong>to</strong>sowane w BFT . . . . . . . . . . . . 44<br />
3.3.4 Proaktywne odzyskiwanie stanu w BFT . . . . . . . . . . 45
4 SPIS TREŚCI<br />
3.4 Algorytm SC-ABC . . . . . . . . . . . . . . . . . . . . . . . . . 46<br />
3.4.1 Kryp<strong>to</strong>grafia progowa . . . . . . . . . . . . . . . . . . . 48<br />
3.4.2 S<strong>to</strong>s pro<strong>to</strong>kołów SC-ABC . . . . . . . . . . . . . . . . . 50<br />
3.4.3 Działanie algorytmu SC-ABC . . . . . . . . . . . . . . . 54<br />
3.5 Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />
4 Tolerowanie bizantyjskich uszkodzeń 61<br />
4.1 Algorytm <strong>na</strong>iwny . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />
4.2 Założenia projek<strong>to</strong>we . . . . . . . . . . . . . . . . . . . . . . . . 63<br />
4.3 Zestaw dostępnych operacji . . . . . . . . . . . . . . . . . . . . . 67<br />
4.4 Pro<strong>to</strong>kół zachłanny . . . . . . . . . . . . . . . . . . . . . . . . . 69<br />
4.5 Zatwierdzanie stanu . . . . . . . . . . . . . . . . . . . . . . . . . 78<br />
4.6 Pro<strong>to</strong>kół optymistyczny . . . . . . . . . . . . . . . . . . . . . . . 82<br />
4.7 Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . 83<br />
5 Projekt systemu Pas<strong>to</strong>r 85<br />
5.1 Projekt systemu . . . . . . . . . . . . . . . . . . . . . . . . . . . 85<br />
5.1.1 Język implementacji - Java . . . . . . . . . . . . . . . . 86<br />
5.1.2 Bezpieczeństwo wyko<strong>na</strong>nia . . . . . . . . . . . . . . . . 86<br />
5.1.3 Postarzanie obiektów . . . . . . . . . . . . . . . . . . . . 89<br />
5.1.4 Zarządzanie dostępem . . . . . . . . . . . . . . . . . . . 92<br />
5.2 Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />
A Elementy teorii grafów 97<br />
A.1 Spójność krawędziowa i wierzchołkowa . . . . . . . . . . . . . . 98<br />
A.2 Różne typy grafów . . . . . . . . . . . . . . . . . . . . . . . . . 98<br />
A.2.1 Grafy regularne i grafy losowe . . . . . . . . . . . . . . 99<br />
A.2.2 Grafy Butterfly . . . . . . . . . . . . . . . . . . . . . . . 100<br />
A.2.3 Grafy de Bruijn’a . . . . . . . . . . . . . . . . . . . . . . 100<br />
B Uzgadnianie w asynchronicznym systemie 103<br />
B.1 Brak konsensusu i asynchroniczność . . . . . . . . . . . . . . . . 103<br />
B.2 Uzgadnianie z częściowym zachowaniem poprawności . . . . . . 107
Rozdział 1<br />
Wprowadzenie<br />
Zgodnie z empirycznym prawem Moore’a szybkość komputerów podwaja się<br />
mniej więcej co pół<strong>to</strong>ra roku 1 . W przypadku sieci przepus<strong>to</strong>wość łączy podwaja<br />
się średnio co pół roku 2 . Zwiększanie przepus<strong>to</strong>wości sieci powoduje, iż<br />
coraz częściej aplikacje korzystają z przetwarzania rozproszonego. Na chwilę<br />
obecną mówi się o architekturach z rozproszeniem wertykalnym i horyzontalnym<br />
[TS01] oraz typu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Pierwsze wymienione obejmują architektury<br />
wielowarstwowe, w których aplikacje mają hierarchiczną budowę i <strong>na</strong>jczęściej<br />
s<strong>to</strong>sowane są w aplikacjach biznesowych 3 . Horyzontalne rozproszenie obejmuje<br />
systemy złożone z komponentów o różnym przez<strong>na</strong>czeniu współpracujących ze<br />
sobą. Architekturę typu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> posiadają systemy składające się z zespołu<br />
współpracujących, logicznie ekwiwalentnych jednostek.<br />
W związku z powyższym coraz częściej <strong>na</strong>turalnym środowiskiem pracy<br />
różnego typu aplikacji jest global<strong>na</strong> sieć - Internet. Systemy informatyczne są<br />
podzielone <strong>na</strong> fizyczne komponenty częs<strong>to</strong>kroć zlokalizowane w geograficznie<br />
odrębnych zakątkach globu, objęte całkowicie niezależną jurysdykcją.<br />
Ekspozycja środowisk komputerowych w ogólnie dostępnej sieci wymaga<br />
z<strong>na</strong>cznie mocniejszych zabezpieczeń chroniących przed nieau<strong>to</strong>ryzowanym dostępem,<br />
podsłuchem i celowymi atakami. Niejednokrotnie brak mechanizmów<br />
zabezpieczeń zupełnie uniemożliwia systemom bezawaryjne działanie.<br />
W tej pracy przedstawiono zagadnienie zapewnienia <strong>to</strong>lerancji błędów bizan-<br />
1 Od 2004 roku wydaje się, że zwiększanie mocy obliczeniowej komputerów zaczy<strong>na</strong> odbiegać<br />
od prawa Moore’a.<br />
2 W przypadku sieci zwiększanie przepus<strong>to</strong>wości <strong>na</strong>stępuje rzadziej niż ma <strong>to</strong> miejsce w<br />
przypadku zwiększania mocy obliczeniowej, ale przeważnie szybkość zmienia się o cały rząd<br />
wielkości (np. 10MBit, 100MBit, 1GBit).<br />
3 Takimi systemami są aplikacje dostępu do bazy danych oparte <strong>na</strong> tzw. cienkim kliencie<br />
(ang. thin client). Najniższą warstwę w architekturze stanowi baza danych. W kolejnej warstwie<br />
z<strong>na</strong>jduje się serwer aplikacji, który odpowiedzialny jest za wyko<strong>na</strong>nie logiki. Najwyższa warstwa<br />
<strong>to</strong> wspomniane oprogramowanie dostępowe, czyli cienki klient.
6 Rozdział 1. Wprowadzenie<br />
tyjskich 4 w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> oraz pokazano techniki możliwe do wykorzystania<br />
podczas projek<strong>to</strong>wania i implementacji tego typu systemów. Głównym<br />
celem stawianym w pracy jest opracowanie me<strong>to</strong>dy bezpiecznej replikacji dla<br />
systemów luźno powiązanych (między innymi <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>), która wykazywałaby<br />
dużą odporność <strong>na</strong> uszkodzenia, zarówno uwzględniając całkowite zaprzestanie<br />
działania repliki, jak i jej arbitralne zachowanie. Replikacja jest główną<br />
me<strong>to</strong>dą podnoszenia odporności <strong>na</strong> awarię i <strong>to</strong>lerowanie uszkodzeń, jed<strong>na</strong>k wymaga<br />
efektywnych me<strong>to</strong>d synchronizacji, które muszą charakteryzować się dużym<br />
bezpieczeństwem. W <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> sposobem <strong>na</strong> podniesienie<br />
bezpieczeństwa może być również wzajemny audyt uczestników. Obie techniki<br />
mogą zostać zrealizowane <strong>na</strong> bazie algorytmu <strong>bizantyjskie</strong>go uzgadniania, którego<br />
propozycje zostały szczegółowo opisane.<br />
1.1 Zawar<strong>to</strong>ść poszczególnych rozdziałów<br />
W dalszej części pierwszego rozdziału opisano krótko genezę systemów <strong>peer</strong><strong>to</strong>-<strong>peer</strong><br />
i przedstawiono problemy bezpieczeństwa występujące w tej klasie systemów.<br />
W rozdziale drugim omówione zostały architektury systemów <strong>peer</strong>-<strong>to</strong><strong>peer</strong><br />
z przez<strong>na</strong>czeniem większej ilości miejsca dla ustrukturalizowanych systemów<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> oraz podstaw teoretycznych ich konstrukcji [LKRG03]. W<br />
tym samym rozdziale pokazane zostały trzy podstawowe usługi budowane <strong>na</strong><br />
bazie systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>: rozproszone tablice z kodowaniem mieszającym<br />
(ang. distributed hashing tables), rozproszo<strong>na</strong> lokalizacja i dostęp do obiektów<br />
(ang. distributed object location and routing) oraz usługa komunikacji grupowej<br />
(ang. multicast, anycast). W rozdziale drugim zostały przedysku<strong>to</strong>wane problemy<br />
bezpieczeństwa ze szczególnym <strong>na</strong>ciskiem <strong>na</strong> zagadnienie bezpiecznego<br />
trasowania oraz utrzymania spójności danych w rozproszonych tablicach z kodowaniem<br />
mieszającym. W trzecim rozdziale zebrane zostały informacje dotyczące<br />
pro<strong>to</strong>kołów bezpiecznego <strong>bizantyjskie</strong>go uzgadniania BFT i SC-ABC. Czwarty<br />
rozdział został poświęcony projek<strong>to</strong>wi pro<strong>to</strong>kołu bezpiecznego <strong>bizantyjskie</strong>go<br />
uzgadniania przez<strong>na</strong>czonego dla systemów luźno powiązanych. W piątym rozdziale<br />
opisywa<strong>na</strong> jest implementacja tes<strong>to</strong>wego systemu Pas<strong>to</strong>r, który zawiera<br />
mechanizmy poprawiające bezpieczeństwo i odporność <strong>na</strong> uszkodzenia, wyko<strong>na</strong>nego<br />
w ramach pracy magisterskiej. Pas<strong>to</strong>r został oparty <strong>na</strong> <strong>na</strong> implementacji<br />
systemu Pastry oraz jednej z jego aplikacji Past. Rozdział pierwszy i drugi oraz<br />
trzeci i czwarty nie są ściśle ze sobą powiązane i mogą być czytane niezależnie,<br />
<strong>na</strong><strong>to</strong>miast rozdział piąty łączy uprzednio poruszaną tematykę i do zrozumienia<br />
wymaga lektury całości materiału.<br />
Dokument ten został <strong>na</strong>pisany z założeniem, że czytelnik nie miał wcześniej<br />
4 I<strong>na</strong>czej arbitralnego zachowania elementów.
1.2 Geneza systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 7<br />
do czynienia z systemami <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, dlatego z<strong>na</strong>czną część pracy przez<strong>na</strong>czono<br />
<strong>na</strong> poglądowy opis architektur tych systemów, jak również przedstawiono<br />
aspekty teoretyczne ich konstrukcji oparte <strong>na</strong> teorii grafów. Należy zaz<strong>na</strong>czyć,<br />
że w momencie powstawania tego opracowania nie była dostęp<strong>na</strong> żad<strong>na</strong> publikacja<br />
ogólnie traktująca o <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> zarówno w języku polskim, jak<br />
i w języku angielskim, zatem z<strong>na</strong>czny <strong>na</strong>kład pracy włożono w zebranie oraz<br />
podsumowanie aktualnych osiągnięć w tej dziedzinie.<br />
1.2 Geneza systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
W 1999 roku, osiem<strong>na</strong>s<strong>to</strong>latek, Shawn Fanning zmienił dotychczasowe oblicze<br />
przemysłu fonograficznego tworząc program do wymiany plików o <strong>na</strong>zwie<br />
Napster. Uderzenie w przemysł fonograficzny spowodowane było tym, iż z<strong>na</strong>komitą<br />
większość treści możliwych do pobrania dzięki Napsterowi, stanowiły<br />
utwory muzyczne w formacie MP3.<br />
Architektura Napstera była bardzo prosta. Jeden centralny serwer służył do<br />
rejestracji udostępnianych plików. Użytkownik poszukujący określonej treści<br />
wysyłał zlecenie do serwera i otrzymywał listę źródeł, które udostępniały dany<br />
zasób. Następnie aplikacja łączyła się z różnymi komputerami pobierając kolejne<br />
części poszukiwanego pliku. Pomimo wielu niedociągnięć pierwszych wersji,<br />
program zdobył szaloną popularność i szybko pakiety pro<strong>to</strong>kołu Napstera zaczęły<br />
dominować w sieci.<br />
Kopiowanie plików muzycznych chronionych prawami au<strong>to</strong>rskimi stanowi<br />
pogwałcenie prawa, dlatego Napster został oskarżony przez organizację RIAA 5<br />
w grudniu 1999 roku. Werdyktem sądu w lutym 2001 roku <strong>na</strong>kazano zamknięcie<br />
serwisu Napstera.<br />
Z punktu widzenia technicznego Napster nie był wyrafinowanym wy<strong>na</strong>lazkiem,<br />
jed<strong>na</strong>k zainteresowanie ze strony użytkowników oraz precedensowy proces<br />
rozpoczął debatę społeczną dotyczącą aspektów moralnych i prawnych związanych<br />
z ochroną praw au<strong>to</strong>rskich w sieci Internet. W 2000 roku Nullsoft wydał<br />
Gnutellę, pojawiło się również wiele innych aplikacji podobnej architektury (AudioGalaxy,<br />
Morpheus, Bearshare itd.). Pojawienie się Napstera i podobnych systemów<br />
przyciągnęło uwagę badaczy akademickich, którzy rozpoczęli prace <strong>na</strong>d<br />
systemami, które pozbawione byłyby podstawowych wad pierwszych aplikacji<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>:<br />
• Anonimowość - <strong>to</strong>żsamość użytkowników nie powin<strong>na</strong> być łatwa do ustalenia.<br />
5 Recording Industry Association of America
8 Rozdział 1. Wprowadzenie<br />
• Bezpieczeństwo - serwowa<strong>na</strong> zawar<strong>to</strong>ść nie może odbiegać od sugerowanej<br />
(przejaw zaśmiecania i zatruwania) oraz nie może występować zjawisko<br />
cenzurowania, tzn. dostęp do zasobu nie może być blokowany przez stronę<br />
trzecią.<br />
• Skalowalność - system powinien móc operować przy dużej liczbie użytkowników<br />
np. rzędu milionów.<br />
• Decentralizacja - zas<strong>to</strong>sowa<strong>na</strong> jako mechanizm wprowadzający odporność<br />
<strong>na</strong> uszkodzenia i wymuszający samoorganizację.<br />
Wbrew ustaleniom sądowym liczba aplikacji typu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> służących do<br />
wymiany plików drastycznie wzrosła. Obecnie moż<strong>na</strong> pobrać między innymi<br />
<strong>na</strong>stępujące aplikacje klienckie <strong>na</strong>jbardziej popularnych sieci: KaZaa, eDonkey,<br />
eMule, DC++, BitTorrent [Coh03]. W porów<strong>na</strong>niu do Napstera, czy Gnutelli<br />
wymienione aplikacje są z<strong>na</strong>cznie bardziej wyspecjalizowane i wyszukane pod<br />
względem architektury, a liczba ich użytkowników sięga wielu milionów. Na<br />
przykład eMule jest hybrydą sieci Overnet oraz Kademlia [MM02]. Overnet ma<br />
budowę dwuwarstwową z wyróżnieniem serwerów, a Kademlia jest całkowicie<br />
rozproszoną siecią używającą metryki XOR 6 .<br />
Pierwsze systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> zostały zaprojek<strong>to</strong>wane w celu udostępniania<br />
plików w sieci globalnej między dużą liczbą użytkowników. Obecnie eksperymentuje<br />
się z systemami tej klasy w wielu innych zas<strong>to</strong>sowaniach: usługi<br />
<strong>na</strong>zewnicze, np. DNS [CMM02], usługi pocz<strong>to</strong>we, np. E-Mail [KRT03], czy<br />
<strong>na</strong>wet implementację tes<strong>to</strong>wą s<strong>to</strong>su pro<strong>to</strong>kołu IPv6 [ZvRM02].<br />
1.3 Zagadnienia bezpieczeństwa<br />
Tematyka bezpieczeństwa przyjmuje w każdym rodzaju systemów pewną postać,<br />
charakterystyczną dla realizowanych funkcjo<strong>na</strong>lności. I<strong>na</strong>czej ma się sprawa z<br />
systemami operacyjnymi, gdzie bezpieczeństwo przede wszystkim rozumiane<br />
jest w sensie ochrony danych i zasobów tak, by nikt nieupoważniony nie był w<br />
stanie uzyskać nieau<strong>to</strong>ryzowanego dostępu do elementów kontrolowanych przez<br />
system. W przypadku sieci informatycznych zagadnienia bezpieczeństwa koncentrują<br />
się <strong>na</strong> zapewnieniu au<strong>to</strong>ryzowanego dostępu do urządzeń dołączonych<br />
do sieci, przeciwdziałaniu <strong>na</strong>dużyć w postaci <strong>na</strong>dmiernej ilości przesyłanych<br />
danych 7 , czy podsłuchu i podszywania się.<br />
6 Rozpatrując dwa adresy węzów v oraz u, odległość d między nimi da<strong>na</strong> jest jako d =<br />
∑ L<br />
i=0 2c(i) ,c= v ⊕ u. L oz<strong>na</strong>cza długość adresu, <strong>na</strong><strong>to</strong>miast c(i) war<strong>to</strong>ść i-tego bitu w liczbie<br />
c.<br />
7 Chodzi głównie o ataki typu odmowy usługi DoS (ang. Denial of Service).
1.3 Zagadnienia bezpieczeństwa 9<br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> ze względu <strong>na</strong> pewne swoiste cechy wymagają zupełnie<br />
innego sposobu a<strong>na</strong>lizy aspektów bezpieczeństwa. Oczywiście część z tych<br />
zagadnień pozostaje taka sama, jak w przypadku klasycznych systemów, jed<strong>na</strong>k<br />
z<strong>na</strong>komita większość wyraźnie od nich odbiega.<br />
Identyfika<strong>to</strong>ry. Każdy węzeł w systemie <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> rozpoz<strong>na</strong>wany jest za<br />
pomocą unikalnego identyfika<strong>to</strong>ra. Główną trudnością jest zarządzanie identyfika<strong>to</strong>rami,<br />
<strong>na</strong>dzorowanie ich przydzielania oraz kontrolowanie sposobu użytkowania.<br />
Ważność tego zagadnienia jest kluczowa dla prawidłowego działania<br />
systemów tej klasy.<br />
Przekazywanie komunikatów. Część komunikacji w powłokach <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 8<br />
odbywa się w sposób niebezpośredni. Moż<strong>na</strong> porów<strong>na</strong>ć działanie węzła w sieci<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> do routera, który przekazuje komunikaty w przestrzeni identyfika<strong>to</strong>rów.<br />
W przypadku fizycznych urządzeń istnieje możliwość wykrycia <strong>na</strong>dużyć<br />
i niepoprawnego działania. Naprawa usterek i wprowadzenie zabezpieczeń<br />
nie sprawia większego problemu, gdyż zazwyczaj urządzenie z<strong>na</strong>jduje się pod<br />
opieką administra<strong>to</strong>ra sieci, który jest fizyczną osobą (np. Janem Kowalskim),<br />
bądź dostawcą usług sieciowych. Sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> nie posiadają centralnych<br />
mechanizmów administracyjnych, które wymuszałyby <strong>na</strong> użytkownikach zapewnianie<br />
jakości działania uruchomionych przez nich aplikacji. Nie ma gwarancji<br />
<strong>na</strong> <strong>to</strong>, że dany węzeł będzie działał poprawnie lub, że nie zakończy działania w<br />
dowolnej chwili.<br />
Bezpiecz<strong>na</strong> replikacja. Replikacja w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> wykorzystywa<strong>na</strong><br />
jest do zapewnienia większej dostępności informacji oraz odporności <strong>na</strong> uszkodzenia.<br />
Brak gwarancji odnośnie działania węzłów wprowadza nowe zagadnienia<br />
związane z replikacją i wymaga s<strong>to</strong>sowania z<strong>na</strong>cznie bardziej skomplikowanych<br />
algorytmów (np. bezpiecznego <strong>bizantyjskie</strong>go uzgadniania), których omówienie<br />
stanowi meritum tej pracy.<br />
Zatruwanie i zaśmiecanie. Gdy mamy do czynienia z systemami, które udostępniają<br />
usługę wstawienia oraz pozyskiwania danych przez użytkownika, częs<strong>to</strong><br />
dochodzi do <strong>na</strong>dużyć w postaci zatruwania i zaśmiecania [CWC]. Zatruwanie<br />
oz<strong>na</strong>cza wysyłanie treści niezgodnych z ich prawdziwą zawar<strong>to</strong>ścią, a zaśmiecanie<br />
jest wprowadzaniem danych w sieci, których treść niezgod<strong>na</strong> jest z sugerowaną<br />
zawar<strong>to</strong>ścią. Różnica pomiędzy tymi dwoma zachowaniami jest niezwykle<br />
subtel<strong>na</strong>. Pierwszy atak polega <strong>na</strong> aktywnym działaniu węzłów i dezorganizacji<br />
działania oprogramowania (np. przesyłaniu niepoprawnych odpowiedzi <strong>na</strong><br />
8 Terminy sieci, systemy oraz powłoki <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> będą w tej pracy s<strong>to</strong>sowany zamiennie.
10 Rozdział 1. Wprowadzenie<br />
<strong>to</strong>rrent<br />
http<br />
http<br />
<strong>to</strong>rrent<br />
<strong>to</strong>rrent<br />
leech<br />
leech<br />
seed<br />
seed<br />
tracker<br />
leech<br />
leech<br />
seed<br />
Rysunek 1.1: Architektura systemu udostępniania plików BitTorrent.<br />
żądania klientów). Zaśmiecanie polega <strong>na</strong> umieszczaniu obiektu przynęty (ang.<br />
decoy), który imituje prawdziwe obiekty, którymi użytkownicy są zainteresowani<br />
(np. pliki w formacie mp3 zgodne długością i <strong>na</strong>zwą do popularnych utworów<br />
muzycznych). Szczególnie <strong>na</strong>gminnie ten rodzaj ataków występuje w przypadku<br />
systemów udostępniania plików, gdyż jest s<strong>to</strong>sowany przez firmy fonograficzne<br />
do obrony i zniechęcania użytkowników do pobierania danych chronionych prawami<br />
au<strong>to</strong>rskimi. Zarówno przed zaśmiecaniem i zatruwaniem użytkownicy<br />
sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> opracowali me<strong>to</strong>dy obrony, jed<strong>na</strong>k nie są one w stanie całkowicie<br />
wyeliminować istnienia tych zjawisk.<br />
Wszystkie wymienione problemy bezpieczeństwa zostaną dokładniej omówione<br />
w rozdziale drugim.<br />
1.4 Zas<strong>to</strong>sowania sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Aplikacje typu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> budowane są dzięki istnieniu grupy użytkowników,<br />
którzy widzą potencjalną korzyść z użytkowania systemu, lub grupy organizacji<br />
dysponujących wieloma komputerami połączonymi w sieć, które współdziałając<br />
będę mogły realizować duże zadania, trudne do rozwiązania przez jedną,<br />
<strong>na</strong>wet bardzo potężną maszynę. Podam kilka przykładów możliwych zas<strong>to</strong>sowań<br />
systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> poczy<strong>na</strong>jąc od udostępniania plików, które pomimo<br />
interwencji wydawnictw fonograficznych, <strong>na</strong>dal jest jednym z <strong>na</strong>jbardziej popularnych<br />
zas<strong>to</strong>sowań tego typu systemów.
1.4 Zas<strong>to</strong>sowania sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 11<br />
1.4.1 Współdzielenie plików<br />
Odwołam się do prawdziwego pro<strong>to</strong>kołu udostępniania plików BitTorrent 9 ,który<br />
działaniem przypomi<strong>na</strong> bardzo Napstera, jed<strong>na</strong>k jest <strong>na</strong> tyle dobrze zaprojek<strong>to</strong>wany,<br />
że z<strong>na</strong>cznie przewyższa pierwowzór. BitTorrent składa się z <strong>na</strong>stępujących<br />
komponentów (patrz rys. 1.1):<br />
• Obserwa<strong>to</strong>r (ang. tracker) - przechowuje informację <strong>na</strong> temat źródeł i<br />
statusu pobierania.<br />
• Nasionko (ang. seed) - jest <strong>to</strong> użytkownik, który posiada 100% udostępnionego<br />
udziału.<br />
• Pijawka (ang. leech) - jest <strong>to</strong> użytkownik, który jest w trakcie pobierania<br />
zasobu.<br />
• Katalog (ang. direc<strong>to</strong>ry) - jest <strong>to</strong> katalog plików <strong>to</strong>rrent, dostępny dla<br />
użytkowników, np. baza plików udostępnio<strong>na</strong> używając serwera http.<br />
Użytkownik, który chce udostępnić zasób buduje plik typu <strong>to</strong>rrent, który<br />
składa się z informacji <strong>na</strong> temat położeniu punktu dostępowego obserwa<strong>to</strong>ra<br />
oraz zawiera skrót kryp<strong>to</strong>graficzny i <strong>na</strong>zwę udostępnianych plików 10 . Zasób dzielony<br />
jest <strong>na</strong> pewną liczbę fragmentów, która powin<strong>na</strong> zależeć od wielkości i od<br />
liczby potencjalnych zainteresowanych. W pliku <strong>to</strong>rrent zamieszczane są skróty<br />
wszystkich części zasobu. Plik <strong>to</strong>rrent zostaje umieszczony w dostępnym dla<br />
użytkowników katalogu plików (może <strong>to</strong> być serwis interne<strong>to</strong>wy). Użytkownicy<br />
pobierają plik <strong>to</strong>rrent i uruchamiają aplikację, która łączy się z obserwa<strong>to</strong>rem.<br />
Ten z kolei rejestruje pobierającego (jego adres i port, <strong>na</strong> którym <strong>na</strong>słuchuje).<br />
Istnienie obserwa<strong>to</strong>ra wprowadza <strong>na</strong>dzór <strong>na</strong>d procesem pobierania pliku i moni<strong>to</strong>ruje<br />
stan pobrań uczestników. Pobieranie pliku wygląda w ten sposób, że<br />
kawałki zasobu <strong>na</strong>jmniej rozpowszechnione stają się <strong>na</strong>jbardziej prawdopodobne<br />
do pobrania przez tych klientów, którzy mają <strong>na</strong>jwiększe części zasobu skopiowane<br />
oraz odpowiednio szybko wysyłają zawar<strong>to</strong>ść innym uczestnikom 11 . Ta<br />
technika dowar<strong>to</strong>ściowuje uczestników z szybkim łączem i prowadzi do lepszej<br />
replikacji, która dzięki podziałowi zasobu <strong>na</strong> fragmenty pozwala maksymalnie<br />
zrównoleglić proces rozsyłania zawar<strong>to</strong>ści. Tracker opcjo<strong>na</strong>lnie może wymagać<br />
logowania od pobierających. Komunikacja odbywa się poprzez pro<strong>to</strong>kół http lub<br />
https.<br />
9 BitTorrent (http://www.bit<strong>to</strong>rrent.com/)<br />
10 BitTorrent pozwala <strong>na</strong> udostępnianie wielu plików w ramach jednego zasobu.<br />
11 Pro<strong>to</strong>kół wprowadza współczynnik udostępniania równy ilości danych pobranych przez innych<br />
użytkowników, do danych pobranych przez <strong>peer</strong>a.
12 Rozdział 1. Wprowadzenie<br />
Zalety:<br />
Wady:<br />
• Platforma do udostępniania dużych zasobów, popularnych w sieci (np.<br />
dystrybucje systemu Linux), co oszczędza pasmo udostępniającego i przyspiesza<br />
proces pobierania przez zainteresowanych.<br />
• Prosty do zaimplemen<strong>to</strong>wania.<br />
• Administra<strong>to</strong>r obserwa<strong>to</strong>ra ma pełny dostęp do informacji <strong>na</strong> temat pobierających<br />
zasób.<br />
• Zoptymalizowany pod względem wykorzystania pasma.<br />
• Mogą służyć do udostępniania treści niezgodnych z prawem.<br />
• Trudne do wyszukania.<br />
1.4.2 Anonimowe połączenia i trasowanie cebulkowe<br />
Anonimowość w Internecie nie tyko jest jednym z <strong>na</strong>jciekawszych zagadnień<br />
współczesnej socjologi, ale również budzącym z<strong>na</strong>czne kontrowersje i obawy<br />
pośród administra<strong>to</strong>rów sieci komputerowych. Dla użytkownika sieci anonimowość<br />
oz<strong>na</strong>cza, że jest on w stanie wyko<strong>na</strong>ć pewne operacje wywierające wpływ<br />
<strong>na</strong> o<strong>to</strong>czenie (np. wysłanie wiadomości, rejestracja w serwisie interne<strong>to</strong>wym<br />
itp.) i jednocześnie pozostanie on pewny, że wyko<strong>na</strong>nie tych operacji nie pozwoli<br />
ustalić jego <strong>to</strong>żsamości. Jako przykład z prawdziwego życia możemy<br />
wyobrazić sobie zakupy w sklepie. Kupując w miejscu, gdzie nikt <strong>na</strong>s nie z<strong>na</strong> i<br />
płacąc gotówką, istnieje małe prawdopodobieństwo tego, że k<strong>to</strong>ś będzie w stanie<br />
ustalić <strong>na</strong>szą <strong>to</strong>żsamość bez posiadania dodatkowych informacji <strong>na</strong> <strong>na</strong>sz temat.<br />
Anonimowość jest cennym <strong>to</strong>warem więc wiele osób jest w stanie udostępnić<br />
swoje zasoby uzyskując w ten sposób poczucie nierozpoz<strong>na</strong>walności. Jed<strong>na</strong> z<br />
technik, która pozwala uzyskać anonimowość w sieci Internet jest trasowanie<br />
cebulkowe (ang. onion routing). Jego realizacja wymaga użycia systemu <strong>peer</strong><strong>to</strong>-<strong>peer</strong><br />
12 .<br />
Trasowanie cebulkowe. Zakładamy, że każdy użytkownik posiada klucz publiczny<br />
i klucz prywatny dla kryp<strong>to</strong>grafii z kluczem publicznym [RSA77, MVO96].<br />
Klucz publiczny udostępniony jest dla każdego użytkownika. Chcąc <strong>na</strong>wiązać<br />
połączenie użytkownik buduje tzw. cebulkę, losując kolejno uczestników do<br />
12 Trasowanie cebulkowe realizowane jest przez oprogramowanie TOR, które wchodzi w skład<br />
projektu FreeHaven (http://www.freehaven.net/).
1.4 Zas<strong>to</strong>sowania sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 13<br />
Entry<br />
funnel<br />
Exit<br />
funnel<br />
Service<br />
Rysunek 1.2: Poglądowa architektura systemu wspierającego anonimowe połączenia.<br />
stworzenia tunelu. Budowa cebulki zaczy<strong>na</strong> się „od końca”, czyli <strong>na</strong>jpierw szyfrowany<br />
jest cel połączenia kluczem publicznym ostatniego węzła. Następnie adres<br />
ostatniego węzła jest szyfrowany kluczem publicznym przedostatniego węzła<br />
itd. (P k−1 (P k(...) , addr k ),P k – szyfrowanie z kluczem publicznym dla węzła k,<br />
addr k - adres węzła k). Po utworzeniu cebulki użytkownik wysyła ją do pierwszego<br />
węzła, on odszyfrowuje swoją część i odczytuje adres kolejnego węzła, z<br />
którym <strong>na</strong>wiązuje połączenie i wysyła do niego cebulkę. Oczywiście cały mechanizm<br />
wymaga istnienia pro<strong>to</strong>kołu <strong>na</strong>dzoru <strong>na</strong>d działającym połączeniem. Problemem<br />
może wydawać się konieczność posiadania kluczy publicznych węzłów,<br />
które zostaną użyte w tworzeniu połączenia. Rozwiązanie problemu dostępności<br />
kluczy dostarcza mechanizm rozproszonych tablic z kodowaniem mieszającym<br />
omówiony w kolejnym rozdziale. Poglądowy schemat systemu realizującego<br />
trasowanie cebulkowe pokazano <strong>na</strong> rys. 1.2.<br />
Pierwszy węzeł, do którego wysyła<strong>na</strong> jest cebulka <strong>na</strong>zwano lejkiem wejściowym<br />
(ang. entry funnel), <strong>na</strong><strong>to</strong>miast ostatni węzeł oz<strong>na</strong>czony jest, jako lejek<br />
wyjściowy (ang. exit funnel). Czytelnik od<strong>na</strong>jdzie szczegóły <strong>na</strong> temat trasowania<br />
cebulkowego w [SGR97, DMS04] oraz inne podejście do zagwaran<strong>to</strong>wania<br />
anonimowości zaimplemen<strong>to</strong>wane w systemie Tarzan [FM02].<br />
Zalety:<br />
Wady:<br />
• Daje możliwość <strong>na</strong>wiązywania połączeń, które nie są w łatwy sposób możliwe<br />
do zrekonstruowania, gwarantując anonimowość inicja<strong>to</strong>ra komunikacji.<br />
• Ostatni węzeł w tunelu może zostać pociągnięty do odpowiedzialności za<br />
wyko<strong>na</strong>ne operacje, gdyż z poziomu usługi, on jest inicja<strong>to</strong>rem połączenia.
14 Rozdział 1. Wprowadzenie<br />
Proxy<br />
Beacon<br />
Beacon<br />
Service<br />
Beacon<br />
Proxy<br />
Rysunek 1.3: Poglądowa architektura systemu maskującego usługę.<br />
• Utrudnia wykrycie <strong>na</strong>dużyć w postaci ataków <strong>na</strong> systemy komputerowe i<br />
rozsyłania spamu.<br />
1.4.3 Maskowanie usługi<br />
Maskowanie usługi SOS (ang. Security Overlay Services) [KMR02] jest techniką,<br />
która pozwala kontrolować obciążenie chronionego serwisu. Realizacja<br />
techniki podobnie jak w przypadku anonimowych połączeń wymaga użycie systemu<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Elementy SOS:<br />
• Przekaźnik (ang. proxy) - jest punktem dostępowym z<strong>na</strong>nym użytkownikom.<br />
• Z<strong>na</strong>cznik (ang. beacon) - jest łącznikiem między usługą a przekaźnikiem<br />
bezpośrednio wybieranym przez usługę.<br />
Pewne węzły w systemie <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> działają jako dobrze z<strong>na</strong>ne punkty<br />
dostępowe (przekaźniki), w których rejestrują się z<strong>na</strong>czniki, wybierane przez<br />
usługę spośród węzłów sieci. Przekaźniki nie mają wiedzy o położeniu usługi,<br />
zatem cały ruch kierują do z<strong>na</strong>czników. Gdyby, któryś ze z<strong>na</strong>czników został<br />
uszkodzony, <strong>to</strong> usługa może wybrać nowy spośród innych węzłów sieci. Liczba<br />
przekaźników może ulegać zmianie i dos<strong>to</strong>sowywać się do bieżącego obciążenia.<br />
Zalety:<br />
• Równoważenie obciążenia.<br />
• Przeciwdziałanie atakom typu DoS.
1.4 Zas<strong>to</strong>sowania sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 15<br />
Wady:<br />
• Zmniejszanie możliwości ataków poprzez maskowanie położenia usługi.<br />
• Zmniejsza wydajność usługi.<br />
• Mogą służyć do zamieszczania treści i usług niezgodnych z prawem.<br />
W tym rozdziale chciałem wprowadzić czytelnika w tematykę związaną z<br />
systemami <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Na wstępie przedstawiłem niechlubne pochodzenie tej<br />
klasy oprogramowania, jak również bieżące kierunki jego rozwoju. Przedstawiłem<br />
problemy bezpieczeństwa, które stanowią podstawowe zagadnienia podczas<br />
projek<strong>to</strong>wania aplikacji <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>oraz przykłady nietypowych zas<strong>to</strong>sowań, takich<br />
jak trasowanie cebulkowe i maskowanie usługi.
Rozdział 2<br />
Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Rozdział ten przedstawia obecną taksonomię systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> i podstawy<br />
teoretyczne zas<strong>to</strong>sowane do ich konstrukcji. W pierwszej kolejności zostaną<br />
omówione nieustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> (up2p) (ang. unstructured<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> systems), które są częs<strong>to</strong> praktycznie s<strong>to</strong>sowane ze względu <strong>na</strong> ich<br />
prostą budowę i spore doświadczenie projek<strong>to</strong>we. Drugim omówionym typem<br />
systemów będą ustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> (sp2p) (ang. structured<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> systems), których cechą charakterystyczną jest brak jakichkolwiek<br />
punktów centralnych oraz silne podstawy teoretyczne wykorzystane do ich konstrukcji.<br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> zostały w <strong>na</strong>turalny sposób podzielone <strong>na</strong> dwie grupy.<br />
Pierwszą stanowią systemy nieustrukturalizowane, w których struktura grafu<br />
sieci, jaki tworzy się poprzez dołączanie i odłączanie poszczególnych uczestników<br />
jest dowol<strong>na</strong>, poza tym dopuszcza się istnienie tzw. super węzłów, które<br />
są punktami przyłączenia oraz organizują komunikację węzłów uczestniczących.<br />
Sposób określania, który z uczestników zostanie super węzłem odbywa się różnie,<br />
bądź <strong>to</strong> w drodze wolontariatu, bądź za sprawą głosowania.<br />
Interesujące z teoretycznego punktu widzenia wydają się być systemy ustrukturalizowane,<br />
których budowa opiera się <strong>na</strong> specjalnie opracowanych algorytmach<br />
trasowania w przestrzeni adresów węzłów. Takie systemy mają określoną<br />
strukturę grafową sieci, która charakteryzuje się niską <strong>na</strong>jdłuższą ścieżką oraz<br />
wysokim współczynnikiem podziału <strong>na</strong> tzw. klastry. Pracą godną polecenia, badającą<br />
aspekty teoretyczne tego typu sieci jest publikacja D. Loguinov i innych<br />
[LKRG03].<br />
Przy<strong>to</strong>czę roboczą definicję systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, która ma tą podstawową<br />
wadę, iż jest restrykcyj<strong>na</strong> i dyskwalifikuje pewne systemy, które mogłyby być<br />
też uważane jako systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Dalej podam prostszą definicję, jed<strong>na</strong>k<br />
<strong>na</strong> tyle ogólną, że pozwala podciągnąć pod systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> wiele innych<br />
systemów, które niekoniecznie moż<strong>na</strong> za takie uważać.
18 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> są <strong>to</strong> systemy rozproszone, w których oprogramowanie<br />
uruchomione <strong>na</strong> każdym węźle spełnia podobne funkcje, a komunikacja<br />
jest symetrycz<strong>na</strong>. Węzły mają swobodę przyłączania i odłączania od systemu.<br />
Przyjęta definicja pochodzi z pracy D. Liben-Nowella i innych [LNBK02],<br />
w której przedstawiono próbę a<strong>na</strong>lizy dy<strong>na</strong>micznych aspektów systemu Chord<br />
[SMK + 01]. Takie określenie, czym są systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> nie jest wystarczająco<br />
ogólne, gdyż nie pozwala <strong>na</strong> zaklasyfikowanie, np. systemów nieustrukturalizowanych,<br />
jako systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. W up2p dopuszcza się istnienie węzłów<br />
o specjalnym przez<strong>na</strong>czeniu, co z kolei sprawia, że te systemy nie są całkowicie<br />
rozproszone, a komunikacja nie w każdym przypadku jest symetrycz<strong>na</strong>. Bardziej<br />
ogólne sformułowanie przedstawiam poniżej:<br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> są <strong>to</strong> systemy rozproszone, w których<br />
podobne oprogramowanie uruchomione <strong>na</strong> każdym węźle,<br />
komunikuje się bezpośrednio i wspólnie realizuje zadania.<br />
Prostsza definicja jest z kolei niewystarczająca i ma za dużo niedopowiedzeń.<br />
Po pierwsze komunikacja bezpośrednia niekoniecznie neguje istnienie komunikacji<br />
w modelu master-slave, który zakłada podrzędność przy wykonywaniu<br />
zadań, a w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> takiej podrzędności nie ma. Komunikacja<br />
odbywa się raczej w modelu master-master, jeżeli wogóle jest <strong>to</strong> dobre określenie.<br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, wprowadzają zupełnie nowy model komunikacji,<br />
gdzie każdy węzeł może być zleceniodawcą i zleceniobiorcą. Sposób ustanowienia<br />
ka<strong>na</strong>łu komunikacyjnego między węzłami w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> jest<br />
pozbawiony z<strong>na</strong>czenia, gdyż połączenie może powstać w sposób dowolny, <strong>na</strong>wet<br />
używając punktów pośrednich, tak jak odbywa się <strong>to</strong> w sieciach ustrukturalizowanych.<br />
O poprawnym zaklasyfikowaniu systemu, jako systemu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> decydują<br />
pewne swoiste cechy, takie jak skala, swoboda przyłączania i odłączania<br />
się, dążenie do ustanowienia komunikacji bezpośredniej między poszczególnymi<br />
węzłami oraz samoorganizacja ich struktury, co jest cechą nową w s<strong>to</strong>sunku do<br />
wielu istniejących systemów 1 .<br />
Poziom ogólnegnych zas<strong>to</strong>sowań systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> możemy podzielić<br />
<strong>na</strong> trzy grupy [DZDS03]:<br />
DHT - rozproszone tablice z kodowaniem mieszającym (ang. distributed<br />
hashing tables)<br />
DOLR - lokalizację obiektów i trasowanie (ang. distributed object location<br />
and routing)<br />
1 Oczywiście wymienione cechy nie stanowią wszystkich: charakterystyczny jest również,<br />
wszechobecny brak zaufania między węzłami, duża awaryjność poszczególnych elementów, konieczność<br />
s<strong>to</strong>sowania technik kryp<strong>to</strong>graficznych itp.
19<br />
Overlay level<br />
A<br />
B<br />
C<br />
TCP<br />
TCP<br />
TCP<br />
Network level<br />
Rysunek 2.1: Dwie warstwy komunikacyjne oraz routing <strong>na</strong> poziomie aplikacji.<br />
CAST - usługi komunikacji grupowej i rozgłaszania (ang.<br />
multicast, anycast)<br />
broadcast,<br />
Należy zauważyć, że lokalizacja obiektów da się sprowadzić do pierwszego<br />
zas<strong>to</strong>sowania, gdyż każdemu obiek<strong>to</strong>wi możemy <strong>na</strong>dać unikalny identyfika<strong>to</strong>r<br />
i umieścić parę w rozproszonej tablicy z kodowaniem<br />
mieszającym. Trudniejszą funkcjo<strong>na</strong>lnością do praktycznej realizacji jest<br />
rozgłaszanie, gdyż wymaga mechanizmów tworzenia i utrzymywania grupy komunikacyjnej.<br />
Lokalizacja w przypadku rozgłaszania również może zostać użyta<br />
podczas realizacji, jed<strong>na</strong>k wymagane staje się utworzenie dodatkowych mechanizmów<br />
zarządzania grupą i przesyłania komunikatów. Gdy rozpatrujemy architektury<br />
rozgłaszania o niewielkiej liczbie członków w grupie, powinno dążyć się<br />
do lokalizacji poszczególnych uczestników i zgromadzenia ich adresów sieciowych,<br />
by komunikacja miała charakter bezpośredni. W przypadku dużych grup<br />
postępuje się i<strong>na</strong>czej, a mianowicie buduje się drzewa komunikacyjne w obrębie<br />
systemu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> podobnie, jak zostało <strong>to</strong> zrobione w systemie komunikacji<br />
grupowej Scribe [CDKR02].<br />
Komunikacja w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> odbywa się <strong>na</strong> dwóch poziomach.<br />
Pierwszy poziom <strong>to</strong> poziom powłoki (warstwy) (ang. overlay level), gdzie komunikaty<br />
przesyłane są od węzła do węzła używając trasowania w warstwie aplikacji.<br />
Drugi poziom stanowi warstwa sieci (ang. network level). W warstwie<br />
sieci komunikacja odbywa się w sposób bezpośredni między węzłami używając<br />
standardowego pro<strong>to</strong>kołu np. TCP/IP (rysunek 2.1).
20 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
2.1 Nieustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Powstanie tego typu systemów wywodzi się od pierwszych sieci wymiany plików:<br />
Napster oraz Gnutella. Na bazie tych aplikacji powstało wiele unowocześnionych<br />
i zaprojek<strong>to</strong>wanych od początku systemów wymiany plików. Zainteresowanie<br />
świata <strong>na</strong>ukowego oraz komercyjnego tymi systemami pojawiło się ze względu<br />
<strong>na</strong> ich skalowalność, odporność <strong>na</strong> działania intruzów, a może również i rozgłos,<br />
który <strong>to</strong>warzyszył rozprawie przeciwko firmie NullSoft wy<strong>to</strong>czony przez<br />
agencję RIAA. Z czasem zaczęły pojawiać się tzw. szkielety (ang. <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
frameworks), jako <strong>na</strong>rzędzia do budowy rozproszonych aplikacji przy użyciu<br />
sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Wymienię tutaj dwa wiodące komercyjne projekty: Sun Microsystems<br />
JXTA 2 i Microsoft P2PSDK 3 .<br />
Schemat grafu nieustrukturalizowangeo systemu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, może wyglądać,<br />
tak jak przedstawiono <strong>na</strong> rysunku 2.2. Ilustracja pokazuje rejestrację zawar<strong>to</strong>ści<br />
z przez węzeł k oraz próbę jej lokalizacji przez węzeł a:<br />
1. Węzeł k rejestruje zawar<strong>to</strong>ść z w super węźle i.<br />
2. Węzeł a zadaje pytanie super węzłowi c ozawar<strong>to</strong>śćz z parametrem TTL 4<br />
równym 1.<br />
3. Super węzeł c stwierdza, że nie ma zawar<strong>to</strong>ści z i przesyła zapytanie do<br />
f i g z TTL równym 2.<br />
4. Węzły f i g również nie z<strong>na</strong>ją położenia z więc podbijają TTL i przesyłają<br />
zapytanie do i.<br />
5. Węzeł i odpowiada bezpośrednio do a lub przez super węzły, oz<strong>na</strong>jmujący,<br />
że zawar<strong>to</strong>ść z z<strong>na</strong>jduje się u k.<br />
Super węzły w celu zlokalizowania zawar<strong>to</strong>ści z rozsyłają między sobą zapytanie<br />
s<strong>to</strong>sując np. pro<strong>to</strong>kół plotkarski (ang. gossiping pro<strong>to</strong>col) [CRB01].<br />
Równie dobrze moż<strong>na</strong>by posłużyć się pro<strong>to</strong>kołem plotkarskim bezpośrednio, bez<br />
użycia super węzłów. Niestety takie postępowanie ograniczyłoby skalowalność<br />
sytemu. Na podobny problem <strong>na</strong>tknęli się twórcy Gnutelli, która przestała funkcjonować<br />
ze względu <strong>na</strong> problemy wydajnościowe.<br />
2 JXTA (http://www.jxta.org)<br />
3 P2PSDK (http://msdn.microsoft.com/library/en-us/p2psdk/p2p/<br />
portal.asp)<br />
4 Time To Leave - parametr oz<strong>na</strong>cza odległość od źródła w skokach. Przy pewnej war<strong>to</strong>ści<br />
progowej, zapytanie nie jest już dalej rozsyłane. Parametr TTL w podobnej postaci jest używany<br />
w s<strong>to</strong>sie pro<strong>to</strong>kołów TCP/IP.
2.2 Ustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 21<br />
e<br />
h<br />
b<br />
f<br />
a?(z#3)<br />
k!z<br />
k<br />
a<br />
a!(z@k#3)<br />
a?(z#2)<br />
a?(z#3)<br />
a?(z#3)<br />
i<br />
a?(z#1)<br />
c<br />
a?(z#2)<br />
g<br />
j<br />
Super węzeł<br />
Węzeł uczestniczący<br />
Rysunek 2.2: Przykład lokalizacji obiektu w nieustrukturalizowanej sieci p2p<br />
2.2 Ustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Systemy tej klasy zrodziły się z prób wprowadzenia klarownych reguł dotyczących<br />
przesyłania komunikatów <strong>na</strong> poziomie aplikacji. Celem twórców było<br />
wskazanie takich algorytmów i architektury, które byłyby skalowalne oraz zapewniały<br />
stabilność bez wyz<strong>na</strong>czania <strong>na</strong>drzędnych elementów. Ustrukturalizowane<br />
systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> są w pełni rozproszone, brak w nich centralnych punktów<br />
komunikacyjnych i zarządzania.<br />
Problemem, jak dotąd jest stanowczo za mała ilość praktycznych i powszechnie<br />
używanych implementacji, a co za tym idzie, nie są <strong>to</strong> twory zoptymalizowane<br />
i brakuje konkretnych danych tes<strong>to</strong>wych dotyczących ich wydajności i<br />
odporności. Wraz z wzrostem rozproszenia wzrasta również ryzyko <strong>na</strong> ataki w<br />
tych <strong>systemach</strong>. Ogól<strong>na</strong> zasada przy projek<strong>to</strong>waniu wszelkich elementów systemów<br />
bazujących <strong>na</strong> ustrutkturalizowanych sieciach <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, <strong>to</strong> unikanie<br />
centralnych punktów odpowiedzialności.<br />
Liczących się projektów ustrukturalizowanych warstw <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> jest kilka<strong>na</strong>ście.<br />
Do <strong>na</strong>jczęściej wymienianych w literaturze i z praktycznymi zas<strong>to</strong>sowaniami,<br />
zaliczają się cztery pozycje: Chord [SMK + 01], Pastry [RD01b],<br />
Tapestry [ZHS + 03] oraz CAN - Content Addressable Network [RFH + 00]. Wymienione<br />
systemy wraz z Kademlia [MM02] stanowią fragment projektu IRIS<br />
(ang. Infrastructure for Resilient Internet Systems) 5 .<br />
5 Iris (http://project-iris.net/projects.html)
22 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Chord. Opracowany w MIT. Każdy węzeł posiada tablicę wskazań <strong>na</strong> 160<br />
innych węzłów w przestrzeni identyfika<strong>to</strong>rów modulo rozmiar przestrzeni.<br />
Przekazywanie komunikatów odbywa się w jednym kierunku. Oczekiwa<strong>na</strong><br />
1<br />
liczba skoków: log 2 2N, gdzie N oz<strong>na</strong>cza spodziewaną liczbę węzłów w<br />
systemie. Przykładem realizacji oprogramowania opartego <strong>na</strong> sieci Chord<br />
jest CFS - Cooperative File System, który jest rozproszonym systemem<br />
plików przez<strong>na</strong>czonym dla dużych intersieci.<br />
Pastry. Opracowany w Rice University. Przesyłanie komunikatów odbywa<br />
się za pomocą specjalnie przygo<strong>to</strong>wanej tablicy tras, której wskazania w<br />
przestrzeni identyfika<strong>to</strong>rów koncentrują się w bezpośrednim sąsiedztwie<br />
węzła. Oczekiwa<strong>na</strong> liczba skoków: alog 2 bN, gdzie b jest parametrem,<br />
przeważnie b =4oraz a jest stałą.<br />
Tapestry. Opracowany w Berkeley California University. System ten<br />
działa <strong>na</strong> podobnych zasadach, jak Pastry. Głów<strong>na</strong> różnica z<strong>na</strong>jduje się w<br />
algorytmie routingu, oraz tym, że Tapestry nie korzysta z lokalności węzłów.<br />
Adres skoku w Tapestry ustalany jest przy użyciu operacji mod 2 b <strong>na</strong><br />
identyfika<strong>to</strong>rach węzłów zgodnych prefiksem adresu docelowego o kolejne<br />
słowo. Ta procedura <strong>na</strong>zwa<strong>na</strong> została trasowaniem suroga<strong>to</strong>wym (ang.<br />
surogate routing) [ZHS + 03, CDG + 02] lub trasowaniem hiperkostkowym<br />
(ang. hipercube routing) [ADS02]. Oczekiwa<strong>na</strong> liczba skoków: log 2 bN.<br />
CAN (ang. Content Addressable Network). Opracowany w Berkeley California<br />
University. Logiczny adres w przypadku tego systemu dzielony jest<br />
<strong>na</strong> d odcinków. Każdy wpis w tablicy tras posiada d sąsiadów, <strong>na</strong>jbliższych<br />
względem każdego odcinka. Oczekiwa<strong>na</strong> liczba skoków: 1 2 dN 1 d .<br />
2.2.1 Przestrzeń identyfika<strong>to</strong>rów<br />
Zarówno w sieciach typu up2p oraz sp2p każdy z węzłów posiada unikalny<br />
całkowi<strong>to</strong>liczbowy identyfika<strong>to</strong>r, który pochodzi z wcześniej ustalonego zakresu<br />
{0, ..., N}, gdzie N =2 n − 1. Różnica między up2p oraz sp2p polega <strong>na</strong> tym,<br />
iż w up2p węzły mogą dowolnie się łączyć, co prowadzi do stworzenia sieci<br />
o strukturze grafu losowego, za wyjątkiem jednoz<strong>na</strong>cznego określenia węzła,<br />
unikalny identyfika<strong>to</strong>r nie ma tak dużego z<strong>na</strong>czenia w sieci up2p.<br />
W <strong>systemach</strong> sp2p każdy węzeł dąży do <strong>na</strong>wiązania kontaktu z węzłami o<br />
konkretnych identyfika<strong>to</strong>rach, co możliwe jest dzięki odpowiednim algorytmom<br />
przyłączania i trasowania. Cenę za mniej obciążające wyszukiwanie węzłów<br />
płaci się w postaci konieczności utrzymywania struktury sieci.<br />
Rozważmy dla przykładu hipotetyczny system <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, w którym węzły<br />
otrzymują pod jurysdykcję podzbiór adresów z całej przestrzeni adresów N.
2.2 Ustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 23<br />
0<br />
k 1<br />
u 0<br />
v<br />
u<br />
k 1<br />
v<br />
z<br />
k 1<br />
0<br />
u<br />
v<br />
k 2<br />
k 2<br />
k 2<br />
Rysunek 2.3: Operacje <strong>na</strong> przestrzeni adresów wykonywane przez hipotetyczny<br />
system sp2p.<br />
1. W pierwszym kroku do systemu włącza się węzeł v o dowolnym identyfika<strong>to</strong>rze<br />
v id . Ponieważ nie ma innych węzłów w systemie, jest on odpowiedzialny<br />
za obiekty z całej przestrzeni adresowej N.<br />
2. W drugim kroku do systemu włącza się kolejny węzeł u. Mogą zaistnieć<br />
trzy sytuacje. Pierwsza u id >v id w tym przypadku węzeł v dzieli<br />
przestrzeń <strong>na</strong> dwie połówki, w ten sposób, że <strong>na</strong>jpierw ustalane są końce<br />
przedziałów k 1 ,k 2<br />
k 1 = v id + u id − v id<br />
2<br />
k 2 = N + u id − v id<br />
2<br />
Dzięki temu pierwszy i drugi kraniec przedziału oddalony jest równo od<br />
u i v. Następnie v oddaje pod jurysdykcję przedział identyfika<strong>to</strong>rów o<br />
krańcach k 1 ,k 2 węzłowi u. W ten sposób oba węzły mają pod jurysdykcją<br />
obszar tej samej wielkości. Drugi przypadek, <strong>to</strong> gdy u id
24 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
uprzednio opisany przy czym k 2 staje się, którymś krańcem istniejącego<br />
już przedziału. Dalsze podziały niekoniecznie dzielą obszar <strong>na</strong> dwie równe<br />
części.<br />
4. W miarę coraz większej liczby <strong>na</strong>pływających węzłów liczba przedziałów<br />
będzie rosła. Należy zatem ograniczyć <strong>na</strong>jmniejszą możliwą długość przedziału<br />
do stałej war<strong>to</strong>ści, zależnej od N. Gdy węzeł przybędzie do sieci,<br />
ajegoid przypadnie <strong>na</strong> przedział, którego nie da się podzielić, <strong>to</strong> nie<br />
otrzyma on, żadnej przestrzeni pod swoją jurysdykcję z wyjątkiem obiektów<br />
o identyfika<strong>to</strong>rze równym id. Węzeł będzie mógł przejąć przedział,<br />
gdy węzeł, który się nim opiekuje odłączy się od sieci. Ten węzeł przejmie<br />
przedział, którego id będzie <strong>na</strong>jbliższe do id byłego właściciela.<br />
5. Rozpatrzmy przypadek, gdy węzeł u odłączy się od systemu. Wtedy węzeł<br />
v przejmie pod swoją jurysdykcję obszar, który był przypisany u. Oczywiście<br />
ważne jest, by v zdawał sobie sprawę z istnienia węzła m, który<br />
otrzymał pod swoją jurysdykcję inny obszar. Nakłada <strong>to</strong> wymóg, żeby<br />
węzeł, który dzieli swój zbiór identyfika<strong>to</strong>rów przydzielając go przybywającemu<br />
węzłowi informował o tej operacji węzeł, od którego otrzymał<br />
obszar uprzednio.<br />
Opisany powyżej system jest ustrukturalizowanym systemem <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>,<br />
gdy dodatkowo zas<strong>to</strong>suje się dla niego odpowiedni algorytm routingu, uwzględniający<br />
jakie węzły mają być utrzymywane w tablicy tras. Przykład nie pochodzi<br />
z literatury i został opracowany <strong>na</strong> potrzeby tej pracy, chociaż przypomi<strong>na</strong> on<br />
CAN z parametrem d =2.<br />
2.2.2 Trasowanie przedrostkowe<br />
Esencją up2p jest zas<strong>to</strong>sowanie w ich konstrukcji algorytmu trasowania Plax<strong>to</strong><strong>na</strong><br />
[PRR97] do <strong>na</strong>wigacji w przestrzeni identyfika<strong>to</strong>rów. Działanie algorytmu jest<br />
bardzo proste. Bity identyfika<strong>to</strong>ra węzła dzielone są <strong>na</strong> słowa o długości b. Gdy<br />
węzeł odbierze komunikat, <strong>to</strong> sprawdza z<strong>na</strong>ne mu adresy węzłów i szuka takiego<br />
węzła, którego identyfika<strong>to</strong>r jest <strong>na</strong>jbardziej zgodny w sensie przedrostka<br />
z identyfika<strong>to</strong>rem odbiorcy. Jeżeli okazałoby się, że takich identyfika<strong>to</strong>rów jest<br />
kilka, <strong>to</strong> wybierany jest ten, który jest <strong>na</strong>jbliżej adresu docelowego. Musi być<br />
spełniony jeszcze jeden warunek, by algorytm przekazywał komunikaty zawsze<br />
w kierunku celu, a mianowicie tylko taka długość przedrostka jest dopuszczal<strong>na</strong>,<br />
która jest większa od długości zgodnego przedrostka węzła odbierającego komunikat.<br />
Czyli po odebraniu komunikatu węzeł <strong>na</strong>jpierw ustala jak bardzo jego<br />
identyfika<strong>to</strong>r zgodny jest przedrostkiem z identyfika<strong>to</strong>rem celu. Koniec wę-
2.2 Ustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 25<br />
drówki komunikatu <strong>na</strong>stępuje, gdy nie ma takiego węzła, do którego dałoby się<br />
dalej przesłać komunikat lub odbiorca jest adresatem.<br />
Przestrzenie identyfika<strong>to</strong>rów ustalane są dzięki przedrostkom, w tym przypadku<br />
moż<strong>na</strong> mówić raczej o podziale <strong>na</strong> strefy. Wędrujący komunikat <strong>na</strong>jpierw<br />
trafia do strefy, gdzie identyfika<strong>to</strong>ry zaczy<strong>na</strong>ją się od takiego samego słowa, jak<br />
identyfika<strong>to</strong>r docelowy, lub bliżej itd. Ogólnie odpowiada <strong>to</strong> sytuacji przedstawionej<br />
<strong>na</strong> rysunku 2.4.<br />
Pozostaje podać warunek <strong>na</strong> <strong>to</strong> by, wierzchołek był osiągalny z każdego<br />
innego dowolnego wierzchołka w sieci s<strong>to</strong>sując trasowanie przedrostkowe. Trasowanie<br />
przedrostkowe nie wymaga, by graf sieć był określonego typu (patrz<br />
Dodatek A), ale sposób połączenia wierzchołków musi spełniać warunek istnienia<br />
cykli w obrębie stref. Warunek istnienia cykli oz<strong>na</strong>cza <strong>to</strong>, iż musi istnieć<br />
cykl przechodzący przez kolejne strefy jednego poziomu. Identyfika<strong>to</strong>ry węzłów,<br />
które posiadają połączenia <strong>na</strong>leżące do różnych stref muszą być graniczne,<br />
tzn. węzeł o <strong>na</strong>jwiększym identyfika<strong>to</strong>rze w strefie posiada wskazanie do węzła<br />
o <strong>na</strong>jmniejszym identyfika<strong>to</strong>rze w strefie sąsiedniej i <strong>na</strong> odwrót. Oczywiście<br />
istnienie połączeń możliwe jest tylko wtedy, gdy istnieją węzły przy<strong>na</strong>leżące do<br />
danej strefy. Dla przykładu rozważmy <strong>na</strong>jwyższe strefy z rysunku 2.4. Warunek<br />
osiągalności będzie spełniony, gdy dla każdej pary stref o numerach <strong>na</strong>stępujących<br />
po sobie, połączenia węzłów między tymi strefami utworzą cykl, czyli:<br />
{0 → 1 → 0}, {1 → 2 → 1}, {2 → 3 → 2}, {00 → 01 → 00}, {01 → 02 →<br />
01}, {02 → 03 → 02}, {10 → 11 → 10}, {11 → 12 → 11}, {12 → 13 → 12} ...<br />
Dodatkowo wszystkie cykle muszą spełniać warunek, że kolejne wierzchołki w<br />
cyklu połączone są mono<strong>to</strong>nicznie (względem rosnących war<strong>to</strong>ści adresów) i<br />
krawędź prowadząca do innej strefy wychodzi z wierzchołka o <strong>na</strong>jmniejszym<br />
numerze i <strong>na</strong>jwiększym numerze w strefie.<br />
Gdy komunikat jest wysyłany do węzła w obrębie tej samej strefy <strong>na</strong>drzędnej,<br />
<strong>to</strong> nie ma większego problemu z jego dostarczeniem. Jedyny warunek jaki<br />
<strong>na</strong>leży spełnić, <strong>to</strong> taki, by węzły posiadały połączenie między sobą w obrębie<br />
strefy uwzględniając uporządkowanie identyfika<strong>to</strong>rów.<br />
2.2.3 Rozproszone tablice z kodowaniem mieszającym<br />
Postanowiłem poświęcić temu zagadnieniu cały podpunkt, gdyż jest <strong>to</strong> podstawowa<br />
usługa, jaką dostarczają sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Na jej podstawie możne<br />
stworzyć wiele funkcjo<strong>na</strong>lności implemen<strong>to</strong>wanych przez rozproszone aplikacje<br />
sieciowe. Na czym polegają DHT i jak są realizowane w ustrutkuralizowanych<br />
<strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>?<br />
W ustrukturalizowanych <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> używa się specjalnej funkcji,<br />
którą <strong>na</strong>zywa się funkcją mapującą f k : N → N, odpowiada o<strong>na</strong> za wyz<strong>na</strong>czenie<br />
adresu węzła odpowiedzialnego za dany obiekt tzw. replica root. Kolejną
26 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
funkcją, jest funkcja replik f r : N → N, której działanie sprowadza się do wyz<strong>na</strong>czenia<br />
kilku identyfika<strong>to</strong>rów węzłów odpowiedzialnych za obiekt o danym<br />
identyfika<strong>to</strong>rze tzw. replica keys. Funkcja mapująca musi być deterministycz<strong>na</strong><br />
i wyz<strong>na</strong>czać jeden konkretny adres, <strong>na</strong><strong>to</strong>miast funkcja replik niekoniecznie. W<br />
praktyce jed<strong>na</strong>k rzadko s<strong>to</strong>suje się funkcje mapującą i funkcję replik, chociaż<br />
ich użycie poprawiałoby wydajność zapytań o konkretne obiekty.<br />
Każdemu zestawowi danych (obiektów) możemy przypisać identyfika<strong>to</strong>r id,<br />
<strong>na</strong>jlepiej z tej samej przestrzeni, z której pochodzą identyfika<strong>to</strong>ry węzłów w<br />
sieci, który dalej będziemy <strong>na</strong>zywali kluczem. Klucz skojarzony jest ze zbiorem<br />
atrybutów, który go określa (np. dla pliku mogą <strong>to</strong> być poszczególne słowa<br />
występujące w <strong>na</strong>zwie). Każdemu atrybu<strong>to</strong>wi również możemy przypisać unikalny<br />
identyfika<strong>to</strong>r, gdyż atrybut również jest pewnym zestawem danych. Gdy<br />
użytkownik wprowadza dane do systemu wykonuje operację:<br />
put(lista atrybutów, dane)<br />
W tym momencie dane zostały zapamiętane w systemie wraz z określoną<br />
listą atrybutów. W rzeczywistym systemie odbywa się <strong>to</strong> tak, że dla każdego<br />
atrybutu wyliczany jest jego identyfika<strong>to</strong>r i węzeł o <strong>na</strong>jbliższym identyfika<strong>to</strong>rze<br />
do identyfika<strong>to</strong>ra atrybutu zapamiętuje parę < a(i) id ,id >, <strong>na</strong><strong>to</strong>miast węzły<br />
których identyfika<strong>to</strong>ry są <strong>na</strong>jbliższe do id zapamiętują parę .<br />
Użytkownik poszukujący danych podaje bezpośrednio id (sytuacja rzadka),<br />
lub listę atrybutów (sytuacja, częsta), otrzymuje w ten w odpowiedzi listę adresów<br />
dojść do danych odpowiadającą liście atrybutów, lub bezpośrednio dane<br />
wskazane poprzez id. Operacja, która wykonuje zapytanie wygląda <strong>na</strong>stępująco:<br />
lista danych = get(lista atrybutów)<br />
W przypadku, gdy lista atrybutów, jest ograniczo<strong>na</strong> do jednej unikalnej war<strong>to</strong>ści,<br />
<strong>to</strong> otrzymamy prostą tablicę adresowań. W innej sytuacji, gdy przyporządkowanie<br />
jest typu jeden-do-wielu, czyli jeden klucz, dla kilku obiektów,<br />
<strong>to</strong> usługa działa, jak tablica z kodowaniem mieszającym (ang. hashing table).<br />
Do poprawnego działania pokazanego schematu wystarczy, aby klucz obiektu<br />
był generowany jako wynik działania bezkolizyjnej funkcji skrótu <strong>na</strong> danych i<br />
atrybutach.<br />
Wymienione uprzednio podstawowe usługi realizowane <strong>na</strong> warstwie <strong>peer</strong>-<strong>to</strong><strong>peer</strong><br />
prowadzą do ogólnej postaci interfejsu programistycznego zaproponowanego<br />
w [DZDS03].<br />
DHT DOLR CAST<br />
put(key, data) publish(objectId) join(groupId)<br />
remove(key) unpublish(objectId) leave(groupId)<br />
data = get(key) sendToObj(msg, objectId, n) multicast(msg, groupId)<br />
anycast(msg, groupId)
2.3 Architektura systemów Chord i Pastry 27<br />
DHT oz<strong>na</strong>cza rozproszone tablice z kodowaniem mieszającym, DOLR, <strong>to</strong><br />
rozproszo<strong>na</strong> lokalizacja obiektów, CAST oz<strong>na</strong>cza usługi rozgłaszania. Trudno<br />
rozpatrzeć, czy zaproponowany zestaw operacji, jest wystarczający, <strong>na</strong> pewno<br />
nie jest kompletny dla wszystkich typów zas<strong>to</strong>sowań.<br />
2.3 Architektura systemów Chord i Pastry<br />
W każdym z opisywanych w tym rozdziale systemów mamy do czynienia z<br />
pewną przestrzenią identyfika<strong>to</strong>rów (adresów, kluczy). Przestrzeń ta <strong>na</strong>jczęściej<br />
jest niczym innym jak podzbiorem liczb całkowitych 〈0, 2 n − 1〉 z<strong>na</strong>cznie liczniejsza<br />
niż przewidywa<strong>na</strong> liczba węzłów uczestniczących w komunikacji. Węzeł<br />
przyłączając się do systemu otrzymuje identyfika<strong>to</strong>r z tej przestrzeni. Dla systemu<br />
Chord, Pastry i Tapestry przyjęło mówić się o pierścieniu identyfika<strong>to</strong>rów,<br />
chociaż tak <strong>na</strong>prawdę jedynie w przypadku Chord’a <strong>to</strong> stwierdzenie ma sens,<br />
gdyż w tym systemie komunikaty wędrują zgodnie ze wzrastającymi war<strong>to</strong>ściami<br />
adresów, łącznie z przekroczeniem zera.<br />
Chord. Każdemu węzłowi przypisywany jest unikalny identyfika<strong>to</strong>r v id zpewnej<br />
przestrzeni identyfika<strong>to</strong>rów N. Następnie węzeł v od<strong>na</strong>jduje swojego poprzednika<br />
i <strong>na</strong>stępnika względem identyfika<strong>to</strong>ra id, który istnieje w systemie. Chord<br />
używa 160-bi<strong>to</strong>wych identyfika<strong>to</strong>rów. W kolejnym kroku węzeł v szuka <strong>na</strong>jbliższych<br />
węzłów względem v id +2 i mod N 7 , gdzie i ∈{0, ..., L(N)}, czyli w<br />
tym przypadku L(N) = 160, i zapamiętuje z<strong>na</strong>lezione identyfika<strong>to</strong>ry węzłów w<br />
tablicy wskazań (ang. finger table). Chord s<strong>to</strong>suje procedurę odświeżania pierścienia<br />
(ang. idealization), która odszukuje nowego poprzednika i <strong>na</strong>stępnika,<br />
jak również uzupełnia wpisy w tablicy wskazań. Zgodnie z trasowaniem prefiksowym<br />
po odebraniu komunikatu przez węzeł sprawdzane jest id odbiorcy i<br />
komunikat przesyłany jest do <strong>na</strong>jbliższego węzła względem identyfika<strong>to</strong>ra, który<br />
z<strong>na</strong>jduje się w tablicy wskazań. Gdyby taki węzeł nie istniał, <strong>to</strong> komunikat dostarczony<br />
jest do aplikacji i o<strong>na</strong> podejmuje decyzję, czy został on poprawnie lub<br />
błędnie odebrany.<br />
Pastry. Podobnie, jak w systmie Chord, węzły oz<strong>na</strong>czone są unikalnymi identyfika<strong>to</strong>rami.<br />
Każdy węzeł v w Pastry utrzymuje trzy pod-tablice routingu. Pierwsza<br />
została <strong>na</strong>zwa<strong>na</strong> tablicą liści (ang. leaf set), w której węzeł przechowuj adresy<br />
innych węzłów, których identyfika<strong>to</strong>ry z<strong>na</strong>jdują się w jego o<strong>to</strong>czeniu (jest <strong>to</strong><br />
przedział o krańcach równych v id ± l/2, gdzie L jest parametrem, a v id jest identyfika<strong>to</strong>rem<br />
węzła v. Liczba węzłów przechowywa<strong>na</strong> w tablicy liści jest zależ<strong>na</strong><br />
od parametru l. Kolejną jest tablica routingu (ang. route set), która ma log 2 b N<br />
7 Ze względu s<strong>to</strong>sowania operacji dzielenia modulo Chord zasługuje <strong>na</strong> miano pierścienia.
28 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
Pastry, b=2<br />
v = 0112<br />
0<br />
00 01 02 03<br />
0 1 2 3<br />
2 n - 1<br />
Rysunek 2.4: Wskazania tablicy routingu węzła v <strong>na</strong> różne framgenty przestrzeni<br />
adresowej w systemie Pastry dla n =8i b =2.<br />
wierszy oraz 2 b kolumn. W wierszu r gromadzi się adresy węzłów, których<br />
identyfika<strong>to</strong>r ma r wspólnych słów o długości b z identyfika<strong>to</strong>rem v. Kolum<strong>na</strong><br />
c ∈{0, ..., 2 b − 1} zawiera identyfika<strong>to</strong>ry z r +1 słowem równym c. Na rysunku<br />
2.4 umieszczono ilustrację wskazań tablicy routingu dla hipotetycznego systemu<br />
Pastry. Charakterystyczne jest, że w Pastry liczba połączeń w sąsiedztwie węzła<br />
rośnie, <strong>na</strong><strong>to</strong>miast w kierunkach dalszych połączeń jest z<strong>na</strong>cznie mniej. Trzecia<br />
tablica nosi <strong>na</strong>zwę tablicy sąsiadów neighbour set. Sąsiadami oz<strong>na</strong>czone są te<br />
węzły, które bliskie są węzłowi v używając innej metryki niż tej określonej <strong>na</strong><br />
przestrzeni identyfika<strong>to</strong>rów. Na przykład miarą s<strong>to</strong>sowaną dla tablicy sąsiedztwa<br />
może być odległość w sensie czasu przesyłania komunikatu. Tablica sąsiadów<br />
ma <strong>na</strong> celu przyspieszenie przesyłania komunikatów wykorzystując rzeczywiste<br />
położenie węzłów w sieci fizycznej.<br />
2.3.1 Algorytm routingu<br />
W ustrukturalizowanych <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> komunikaty zawsze wędrują poprzez<br />
kilka węzłów. Budzi <strong>to</strong> uzasadnione obawy, gdyż możemy łatwo wyz<strong>na</strong>czyć<br />
prawdopodobieństwo p tego, że komunikat zostanie poprawnie dostarczony,<br />
gdy f-ta część węzłów nie działa prawidłowo. Wyraz <strong>na</strong> prawdopodobieństwo<br />
przyjmuje postać p =(1−f) h , gdzie h oz<strong>na</strong>cza liczbę skoków (hops) jakie musi<br />
wyko<strong>na</strong>ć komunikat, by dotrzeć do celu. Jeżeli operujemy w systemie ustrukturalizowanym,<br />
gdzie maksymal<strong>na</strong> liczba skoków częs<strong>to</strong> wyraża<strong>na</strong> jest przez<br />
a · log 2 bN, gdzie a oraz b <strong>to</strong> parametry, a N <strong>to</strong> liczba węzłów uczestniczących<br />
w komunikacji, <strong>to</strong> p =(1− f) a·log 2 bN . Czyli już dla N =10 6 i b =4, p może<br />
być dosyć małe <strong>na</strong>wet przy niewielkim f. Rozwiązanie tego problemu wymaga<br />
zas<strong>to</strong>sowania technik bezpiecznego trasowania oraz proaktywnego usuwania niepoprawnie<br />
działających węzłów.
2.3 Architektura systemów Chord i Pastry 29<br />
Routing w Pastry. Niech L oz<strong>na</strong>cza zbiór liści, R tablicę routingu, N zbiór<br />
sąsiadów, d identyfika<strong>to</strong>r węzła docelowego, l ∈ L identyfika<strong>to</strong>ry węzła <strong>na</strong>leżącego<br />
do zbioru liści, p(a, b) wspólną długość w z<strong>na</strong>kach współdzieloną między<br />
identyfika<strong>to</strong>rem a i b, R j i , wpis w tablicy routingu dla kolumny i oraz wiersza<br />
j, d(k) będzie k-tym z<strong>na</strong>kiem w identyfika<strong>to</strong>rze k.<br />
Każdy węzeł a odbierając komunikat zaadresowany do d wykonuje <strong>na</strong>stępujące<br />
kroki:<br />
Jeżeli d ∈ L, <strong>to</strong> przekaż d do arg min l∈L |d − l|<br />
Niech k = p(a, d). Jeżeli R k d(k) nie jest puste, <strong>to</strong> przekaż komunikat do<br />
R k d(k) , w przeciwnym razie przekaż komunikat do węzła t ∈ L ∪ R ∪ N<br />
dla, którego spełnione jest p(t, d) ≥ k i |t − d| < |a − d|<br />
Jeżeli adresat <strong>na</strong>leży do zbioru liści, <strong>to</strong> komunikat zostanie przekazany do<br />
węzła, którego id jest <strong>na</strong>jbliższe względem celu. Gdy adresat jest spoza zakresu<br />
węzłów <strong>na</strong>leżących do zbioru liści, <strong>to</strong> przegląda<strong>na</strong> jest tablica routingu i wybierany<br />
jest wpis, w którym identyfika<strong>to</strong>r jest <strong>na</strong>jbardziej zgodny przedrostkiem z<br />
celem, o ile takowy istnieje. W innym przypadku przeszukiwane są wszelkie<br />
dostępne zbiory identyfika<strong>to</strong>rów i jako kolejny skok wybierany jest taki węzeł,<br />
którego cześć wspól<strong>na</strong> przedrostka identyfika<strong>to</strong>ra zgod<strong>na</strong> jest przy<strong>na</strong>jmniej tak<br />
dobrze jak węzła, który odebrał komunikat, a odległość od celu określo<strong>na</strong> używając<br />
miary euklidesowej jest mniejsza.<br />
2.3.2 Przyłączanie do systemu<br />
Zilustruję działanie routingu w ustrukturalizowanych sieciach <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> <strong>na</strong><br />
przykładzie przyłączania więzła o identyfika<strong>to</strong>rze ′ x ′ − 1330 do systemu miniPastry.<br />
Różnica między miniPastry, a Pastry polega <strong>na</strong> tym, że przestrzeń<br />
identyfika<strong>to</strong>rów została ograniczo<strong>na</strong> do 2 7 −1. Identyfika<strong>to</strong>ry mogą przyjmować<br />
postać z<strong>na</strong>ków w kodowaniu ASCII, stąd id węzła oz<strong>na</strong>czono ′ x ′ , czyli 1330 w<br />
zapisie czwórkowym. Na rysunku 2.5 z<strong>na</strong>jduje się tablica trasowań dla węzła<br />
′ W ′ . Dla przypomnienia tablica trasowań w Pastry podzielo<strong>na</strong> jest <strong>na</strong> trzy części,<br />
pierwsza część gromadzi adresy z bezpośredniego o<strong>to</strong>czenia, druga część zbiera<br />
adresy w różnych podprzestrzeniach pierścienia (w i-tym wierszu z<strong>na</strong>jdują się<br />
adresy zgodne co do i słów z adresem węzła, dla którego jest tablica, w j-tej<br />
kolumnie z<strong>na</strong>jduje się adres z j tym słowem zgodnym, i oraz j numerowane są<br />
od zera), a trzecia przechowuje wskazania <strong>na</strong> węzły będące w sąsiedztwie np.<br />
względem metryki. Niech długość słowa w adresie wynosi b =2(stąd zapis<br />
czwórkowy).
30 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
WEZEL W - 1113<br />
t<br />
x<br />
z<br />
2 7 -1<br />
j(x)<br />
S 1103<br />
T 1110<br />
ZBIÓR LISCI<br />
U 1111<br />
X 1120<br />
V 1112<br />
Y1121<br />
ZBIÓR TRAS<br />
Z 1122<br />
[ 1123<br />
W<br />
j(x)<br />
j(x)<br />
x<br />
(sp) 0200<br />
B 1002<br />
R 1102<br />
T 1110<br />
###<br />
###<br />
###<br />
U 1111<br />
} 2001<br />
###<br />
[ 1123<br />
V 1112<br />
###<br />
t 1320<br />
_ 1133<br />
###<br />
0<br />
? 333<br />
ZBIÓR SASIADÓW<br />
###<br />
` 1200<br />
~ 2002<br />
L 1030<br />
### q 1311<br />
###<br />
Rysunek 2.5: Przykład przyłączania do sieci miniPastry<br />
Przyłączanie odbywa się przez węzeł 0. Gdy węzeł x oz<strong>na</strong>jmi chęć przyłączenia<br />
węzłowi 0 ten wysyła specjalny komunikat j(x) w kierunku o<strong>to</strong>czenia x.<br />
Każdy z węzłów biorący udział w komunikacji odsyła swoją tablicę trasowań do<br />
x, tak że x jest w stanie zbudować własną tablicę trasowań.<br />
Węzeł W po otrzymaniu j(x) sprawdzi swoją tablicę liści i stwierdzi, że nie<br />
ma w niej x dlatego <strong>na</strong>stępnie sprawdzi tablicę tras <strong>na</strong>jpierw określając dla ilu<br />
początkowych słów adres x zgadza się z jego własnym adresem, czyli tylko<br />
pierwsze słowo z adresu będzie zgodne z adresem celu, dlatego węzeł W wybierze<br />
wiersz pierwszy (1). Dalej W sprawdzi kolejne słowo adresu x w celu<br />
określenia odpowiedniej kolumny. War<strong>to</strong>ść słowa <strong>na</strong> drugiej pozycji <strong>to</strong> trzy (3),<br />
zatem <strong>na</strong>leży wybrać trzecią kolumnę (czwartą, gdy liczymy od zera). Z<strong>na</strong>jduje<br />
się tam wpis t i on stanie się docelowym punktem, dla komunikatu. Tablica sąsiadów<br />
w Pasty przechowuje wskazania <strong>na</strong> węzły <strong>na</strong>jbliższych w sensie metryki<br />
dla warstwy sieci (np. czas przesłania komunikatu używając pro<strong>to</strong>kołu UDP).<br />
Rodzaj metryki dla tablicy sąsiadów może być różnie określony w zależności od<br />
zas<strong>to</strong>sowania, np. może być <strong>to</strong> metryka względem czasu przesyłania komunikatu<br />
lub odległości liczonej w skokach. Węzeł W powinien sprawdzić po określeniu<br />
punktu docelowego, czy żaden inny węzeł w tablicy sąsiadów nie leży również<br />
blisko celu, w ten sposób moż<strong>na</strong> próbować przyspieszyć przesłanie komunikatu.<br />
2.4 Bezpieczeństwo w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
W pierwszym rozdziale zostały zasyg<strong>na</strong>lizowane problemy bezpieczeństwa, które<br />
mogą wystąpić w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. W tym paragrafie zostaną one ponow-
2.4 Bezpieczeństwo w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 31<br />
nie omówione z szczególnym uwzględnieniem charakterystyki systemów up2p<br />
bez rozpatrywania problemów dotyczących konkretnych zas<strong>to</strong>sowań, takich jak<br />
udostępnianie plików, itp.<br />
2.4.1 Klasyczne problemy bezpieczeństwa<br />
Każda grupa aplikacji, która działa w środowisku otwartym, takim jakim jest sieć<br />
Internet powin<strong>na</strong> spełniać pewne podstawowe usługi bezpieczeństwa [MVO96]:<br />
• Integralność danych - zawar<strong>to</strong>ść komunikatów powin<strong>na</strong> być możliwa do<br />
weryfikacji, tak by moż<strong>na</strong> było ustalić czy podczas przesyłania komunikat<br />
nie został on zmodyfikowany.<br />
• Niezaprzeczalność - powin<strong>na</strong> istnieć możliwość jednoz<strong>na</strong>cznego określenia<br />
<strong>na</strong>dawcy informacji. Nadawca nie powinien być w stanie wyprzeć się, że<br />
wiadomość została <strong>na</strong>da<strong>na</strong> przez niego.<br />
• Poufność - informacje powinny być możliwe do odczytania tylko przez<br />
adresatów.<br />
• Uwierzytelnianie - powin<strong>na</strong> istnieć możliwość weryfikacji <strong>to</strong>żsamości <strong>na</strong>dawcy.<br />
Powyższe wymagania pozwalają spełnić klasyczne techniki kryp<strong>to</strong>graficzne,<br />
jed<strong>na</strong>k z pewnym wyjątkiem. Niestety usługa niezaprzeczalnościi nie zawsze<br />
jest możliwa do osiągnięcia, gdyż w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> rzadko s<strong>to</strong>suje się<br />
weryfikowalne podpisy cyfrowe, a <strong>to</strong> z tego powodu iż przy tak dużej ilości<br />
użytkowników jakikolwiek punkt centralnej weryfikacji stanowiłby wąskie gardło.<br />
Częs<strong>to</strong> <strong>na</strong><strong>to</strong>miast s<strong>to</strong>suje się techniki z kluczem publicznym bez zaufanej<br />
strony trzeciej. Użytkownik wystawia certyfikat sobie sam, który wiąże jakieś<br />
charakterystyczne informacje z<strong>na</strong>ne użytkownikowi z konkretną instancją aplikacji.<br />
Moż<strong>na</strong> się zasta<strong>na</strong>wiać, czy takie postępowanie jest cokolwiek warte? Przy<br />
braku innych me<strong>to</strong>d zapewnienia bezpieczeństwa, jest <strong>to</strong> przy<strong>na</strong>jmniej jakaś me<strong>to</strong>da<br />
prewencji.<br />
Do problemów bezpieczeństwa występujących w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> z<br />
powodzeniem moż<strong>na</strong> dołożyć jeszcze <strong>na</strong>stępujące:<br />
• Ataki typu odmowy usługi - problemy z przyłączeniem do sieci. Zdarza<br />
się, że węzeł nie chce przyłączyć użytkownika do sieci. W tym wypadku<br />
<strong>na</strong>jlepszym podejściem jest wybranie sobie innego punktu przyłączenia.<br />
Brzmi <strong>to</strong> trywialnie, ale unikanie centralnych punktów porażki <strong>to</strong> podstawowa<br />
technika walki z niepożądanym zachowaniem.
32 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
• Zaśmiecanie - umieszczanie danych niezgodnych z przez<strong>na</strong>czeniem. Niestety<br />
idealnej me<strong>to</strong>dy walki z tym rodzajem zachowania nie opracowano.<br />
Węzły czasem cenzorują treści wstawiając konkretnym danym oraz węzłom<br />
poziomy zaufania. Prowadzi <strong>to</strong> do powstania sieci zaufania (ang.<br />
web of trust) pomiędzy węzłami i w powiązaniu do konkretnych danych.<br />
Duża ilość pozytywnych weryfikacji od różnych uczestników może poprawiać<br />
<strong>na</strong>sze zaufanie danych, z którymi przyjdzie <strong>na</strong>m pracować. Podob<strong>na</strong><br />
technika s<strong>to</strong>sowa<strong>na</strong> jest w JXTA [CY01].<br />
• Wstrzykiwanie wirusów - umieszczanie danych potencjalnie niebezpiecznych<br />
w sieciach. Obro<strong>na</strong> s<strong>to</strong>sowa<strong>na</strong> w tym przypadku może uwzględniać<br />
filtrowanie, podobne jakie s<strong>to</strong>suje się wobec spamu. Węzły mogą<br />
współpracować w celu tworzenia syg<strong>na</strong>tury ataków i organizować wspólną<br />
obronę wymieniając informację między sobą.<br />
• Konie trojańskie - wprowadzanie zmodyfikowanych wersji oprogramowania,<br />
które zawierają wirusy i oprogramowanie szperające typu (ang. spyware).<br />
Użytkownicy powinni pobierać kolejne wersje oprogramowania<br />
tylko z zaufanych źródeł i zawsze weryfikować syg<strong>na</strong>tury plików.<br />
2.4.2 Nadawanie identyfika<strong>to</strong>rów<br />
Bezpieczny przydział identyfika<strong>to</strong>rów jest podstawowym i <strong>na</strong>jpoważniejszy problem<br />
w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Identyfika<strong>to</strong>ry nie powinny być generowane<br />
przez użytkowników bez żadnych restrykcji. Wiąże się <strong>to</strong> z jednym z podstawowych<br />
wymagań, które stwierdza, że w sieciach <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> identyfika<strong>to</strong>ry węzłów<br />
powinny być równomiernie rozprowadzone w systemie, tzn. żeby średnio<br />
w każdej stefie była taka sama liczba identyfika<strong>to</strong>rów niezależnie od poziomu.<br />
Kolejnym wymaganiem jest, by jeden klient nie był w stanie uzyskać kilku<br />
identyfika<strong>to</strong>rów bliskich sobie. Gdyby się tak stało, <strong>to</strong> taki uczestnik może<br />
bez problemu cenzorować ruch w sieci, lub <strong>na</strong>wet doprowadzić do rozspójnienia<br />
warstwy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>przesyłając fałszywe informacje lub po prostu blokując cały<br />
ruch przepływający przez węzły, które kontroluje.<br />
Problem wielu „<strong>to</strong>żsamości” przypisanych do jednego użytkownika w literaturze<br />
przedstawiono jako atak typu „Sybil” [Dou02].<br />
Sybil <strong>to</strong> pseudonim Shirley Ardell Mason, która urodziła się 25 stycznia<br />
1923 roku w Doge Center w Minnesocie. W wieku młodzieńczym trafiła do<br />
psychiatry, dr Cornelii Wilbur, która stwierdziła u niej wielo<strong>to</strong>żsamościowe zaburzenie<br />
poczucia osobowości (ang. Multiple Perso<strong>na</strong>lity Disorder). Sybil miała<br />
16 różnych <strong>to</strong>żsamości, które ujawniały się u niej przemiennie lub równocześnie.<br />
Jedynym rozwiązaniem problemu jest wydawanie identyfika<strong>to</strong>rów i certyfikatów<br />
je potwierdzających przez centrum certyfikacyjne. Wielość <strong>to</strong>żsamości
2.4 Bezpieczeństwo w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> 33<br />
może być użytecz<strong>na</strong>, gdyż <strong>na</strong> przykład, węzeł z kilkoma identyfika<strong>to</strong>rami z różnych<br />
stref działa w ramach jednej instancji aplikacji przesyłając komunikaty. W<br />
ten sposób, działa on, jak HUB skracający, drogę komunikatów w przestrzeni<br />
identyfika<strong>to</strong>rów.<br />
2.4.3 Przesyłanie komunikatów<br />
Problem zapewnienia bezpieczeństwa przesyłanym komunika<strong>to</strong>m nie jest trywialny,<br />
gdyż węzły nie wiedzą nic o sobie apriori, a przy<strong>na</strong>jmniej kilka pierwszych<br />
komunikatów wysyłanych gdy węzły chce <strong>na</strong>wiązać połączenie z innym<br />
węzłem, podróżuje jako datagramy przechodząc przez punkty pośrednie. Po<strong>na</strong>d<strong>to</strong><br />
komunikaty mogą umyślnie być zatrzymywane i niszczone przez niepoprawnie<br />
działające węzły pośredniczące. W pierwszym przypadku obro<strong>na</strong> jest<br />
możliwa tylko wtedy, gdy węzły współpracują w obrębie jednej rozproszonej<br />
aplikacji, która może mieć zaszytą pewną wspólną tajną informację, co z kolei<br />
może posłużyć do szyfrowania zawar<strong>to</strong>ści komunikatów. Drugi problem rozwiązuje<br />
się używając <strong>na</strong>stępujących technik: a) randomizacja węzłów używanych<br />
do wysyłania komunikatu (ang. diverse routing) i trasowanie <strong>na</strong>dmiarowe (ang.<br />
redundant routing) b) technika cofania i retransmisji (ang. backtrace) c)użycie<br />
usztywnionych tablic trasowań [CDG + 02]. Trudność w s<strong>to</strong>sowaniu tych technik<br />
spowodowa<strong>na</strong> jest brakiem komunikacji bezpośredniej oraz asymetrycznością<br />
połączeń pośrednich (odpowiedź może wracać zupełnie inną drogą niż żądanie).<br />
Czytelnika zainteresowanego szczegółami wymienionych technik odsyłam<br />
do publikacji [CDG + 02].<br />
2.4.4 Masowe przyłączanie i odłączanie<br />
Atakujący, któremu udało się opanować dużą liczbę węzłów w systemie <strong>peer</strong><strong>to</strong>-<strong>peer</strong><br />
może spróbować rozspójnić sieć. Jest <strong>to</strong> możliwe szczególnie wtedy,<br />
gdy atakujący zdobył kontrolę <strong>na</strong>d węzłami których identyfika<strong>to</strong>ry leżą blisko<br />
siebie w przestrzeni identyfika<strong>to</strong>rów. Zakładając, że niemożliwa jest powyższa<br />
sytuacja (np. istnieje w systemie mechanizm zarządzania identyfika<strong>to</strong>rami), pozostaje<br />
do rozpatrzenia przypadek, gdy węzły odłączają się od systemu masowo.<br />
Równomierne odłączanie węzłów z całej przestrzeni identyfika<strong>to</strong>rów nie spowodowałoby<br />
awarii, o ile liczba węzłów nie przekroczyłaby pewnej war<strong>to</strong>ści 8 .<br />
Masowe wyłączenie węzłów bliskich sobie zdezorganizowałoby sieć a <strong>na</strong>wet<br />
mogłoby doprowadzić do zniszczenia ej struktury.<br />
Masowe przyłączanie może mieć również złe <strong>na</strong>stępstwa. Głównym problemem<br />
z masowym przyłączaniem jest odświeżanie tablic trasowania przez<br />
8 Niestety <strong>na</strong> chwilę obecną brak jest konkretnych danych prezentujących szacunkowe wyliczenia<br />
współczynnika wrażliwości <strong>na</strong> odłączenia dla różnych systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>
34 Rozdział 2. Architektury systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
węzły. W systemie takim jak Pastry, poprawnie wypełnione tablice trasowania<br />
stanowią o poprawnym przekazywaniu komunikatów. Węzły przyłączające powinny<br />
ograniczać szybkość przyłączania s<strong>to</strong>sownie do obciążenia, ewentualnie<br />
powinny s<strong>to</strong>sować mechanizmy równoważenia obciążenia poprzez przekierowywanie<br />
węzłów przyłączających do innych węzłów sieci i odpowiedni przydział<br />
identyfika<strong>to</strong>rów.<br />
Odłączanie replik może spowodować utratę danych dlatego koniecznym wydaje<br />
się s<strong>to</strong>sowanie replikacji opartej <strong>na</strong> algorytmach bezpiecznego uzgadniania,<br />
przedstawionych w kolejnym rozdziale. Is<strong>to</strong>tnym wymaganiem wobec algorytmów<br />
replikacji w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>jest łatwa adaptacja do zmieniającego<br />
się składu grupy replik i bezwzględny brak elementów centralnych.
Rozdział 3<br />
Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
Replikacja jest podstawową techniką s<strong>to</strong>sowaną w DHT do utrzymania danych,<br />
które zostały umieszczone w różnych węzłach systemu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> pod odpowiednimi<br />
kluczami. Wprowadzenie replikacji skutkuje podwyższeniem <strong>to</strong>lerancji<br />
<strong>na</strong> uszkodzenia, jed<strong>na</strong>k wiąże się z koniecznością synchronizacji danych<br />
między replikami. W systemie, gdzie użytkownicy przyłączają się i odłączają w<br />
losowy sposób, techniki replikacji stają się bardzo skomplikowane. Replikacji<br />
moż<strong>na</strong> używać również w związku z różną popularnością obiektów dostępnych<br />
w systemie, dzięki czemu te bardziej pożądane przez użytkowników będą szybciej<br />
i łatwiej osiągalne. Problemy pojawiają się, gdy część replik zawodzi oraz<br />
gdy nie możemy mieć zaufania do działania poszczególnych elementów systemu.<br />
Heterogeniczność oprogramowania i częste umyślne działanie <strong>na</strong> szkodę systemów<br />
informatycznych wymusza s<strong>to</strong>sowanie takich algorytmów replikacji, które<br />
nie tylko zadbają o a<strong>to</strong>mowy dostęp do pożądanego obiektu, ale zagwarantują<br />
poprawność uzyskanych danych. W <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> odporność <strong>na</strong> przypadkowe<br />
bądź złośliwe zachowanie jest koniecznością, gdyż <strong>na</strong>wet mała liczba<br />
źle działających węzłów może spowodować utratę informacji.<br />
Ten rozdział ma <strong>na</strong> celu a<strong>na</strong>lizę obecnie s<strong>to</strong>sowanych algorytmów replikacji<br />
usługi, które zapewniają <strong>to</strong>lerancję bizantyjskich uszkodzeń. Na wstępie został<br />
opisany problem bizantyjskich generałów, który jest klasyczną ilustracją zagadnienia<br />
i wprowadzeniem do problemu <strong>bizantyjskie</strong>go uzgadniania. Następnie<br />
omówiono dwa algorytmy replikacji <strong>to</strong>lerującej błędy <strong>bizantyjskie</strong>, które s<strong>to</strong>sują<br />
całkowicie odmienne techniki, by ostatecznie osiągnąć podobny cel. Oba<br />
przedstawione w tym rozdziale algorytmy nie były projek<strong>to</strong>wane z myślą o <strong>systemach</strong><br />
słabo powiązanych, jed<strong>na</strong>k stanowią dobrą bazę dla algorytmu, który<br />
<strong>na</strong>dawałby się do zas<strong>to</strong>sowania w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Próba opracowania<br />
takiego algorytmu przedstawio<strong>na</strong> jest w <strong>na</strong>stępnym rozdziale.<br />
Większa <strong>to</strong>lerancja uszkodzeń i maskowanie błędów w <strong>systemach</strong> rozproszonych<br />
wymaga rozwiązania dwóch podstawowych problemów:
36 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
• Uszkodzenie/odłączenie repliki (ang. fail-s<strong>to</strong>p behaviour). Replika przestaje<br />
odpowiadać i dalsza komunikacja z nią jest niemożliwa. Replika<br />
może zacząć ponownie odpowiadać.<br />
• Niepoprawne działanie repliki (ang. byzantine behaviour). Replika zarówno<br />
może przestać odpowiadać <strong>na</strong> zlecenia, jak również może wysyłać<br />
komunikaty niezgodne z prawdziwym stanem usługi.<br />
Technika <strong>to</strong>lerowania uszkodzeń replik typu fail-s<strong>to</strong>p, wymaga zas<strong>to</strong>sowania<br />
mechanizmu odzyskiwania stanu (ang. state recovery) przez replikę, która uległa<br />
awarii, oraz utworzenia nowej repliki, gdyby uszkodzo<strong>na</strong> replika nie odzyskała<br />
sprawności. Niepoprawne działanie repliki (celowe, bądź przypadkowe, np. wynikające<br />
z ukrytych błędów implementacyjnych) jest poważniejszym problemem,<br />
którego rozwiązanie musi uwzględniać wprowadzenie mechanizmu uzgadniania<br />
stanu (ang. state agreement) oraz proaktywnego odzyskiwania stanu (ang. proactive<br />
state recovery). Bardziej wnikliwe omówienie rodzajów niepoprawnych<br />
zachowań elementów systemów, czytelnik z<strong>na</strong>jdzie w książce A. Tanenbauma i<br />
M. Van Stee<strong>na</strong> [TS01].<br />
Zagadnienie uzgadniania stanu rozdystrybuowanego pomiędzy R uczestników<br />
zostało sformuowane, jako problem bizanyjskich generałów i od jego <strong>na</strong>zwy<br />
pochodzi określenie <strong>bizantyjskie</strong>go modelu zachowania (ang. byzantine behaviour).<br />
3.1 Problem bizantyjskich generałów<br />
Nazwa zagadnienia wywodzi się z Bizancjum (Cesarstwo Bizantyjskie), wcześniej<br />
wschodniej części Imperium Rzymskiego, państwa którego dzieje rozciągają<br />
się od około IV wieku n.e., aż po zdobycie Konstantynopola w 1453 roku<br />
przez Turków Osmańskich, która <strong>to</strong> data niejednokrotnie wskazywa<strong>na</strong> jest, jako<br />
koniec Średniowiecza. Schyłek (tzw. okres późnobizantyjski) istnienia cesarstwa<br />
datuje się od końca 1204 roku, do wyżej wspomnianego zdobycia jego s<strong>to</strong>licy -<br />
Konstantynopola. W okresie późnobizantyjskim dochodzi do rozbicia cesarstwa<br />
<strong>na</strong> szereg rywalizujących ze sobą państewek (Cesarstwo Łacińskie, Cesarstwo<br />
Nicejskie, Cesarstwo Epirskie, Cesarstwo Trapezuntu) oraz coraz mocniejszej<br />
ingerencji sułtanów osmańskich w ich politykę. Zdrada stała się częstą przyczyną<br />
porażek militarnych w walkach z <strong>na</strong>jazdem tureckim.<br />
Przykład. Czerwony generał wraz z wielką armią stacjonuje w dolinie 1 . Walczą<br />
z nim czterej niebiescy generałowie, którzy okopali swoje pozycje <strong>na</strong> wzgórzach<br />
1 Podany przykład pochodzi z książki A. Tanenbauma [TS01], jed<strong>na</strong>k w tej pracy został<br />
szerzej omówiony.
3.1 Problem bizantyjskich generałów 37<br />
1<br />
x 1<br />
1<br />
3<br />
2<br />
y<br />
2<br />
4<br />
z<br />
4<br />
1<br />
2<br />
2<br />
4 2<br />
4<br />
Krok 1- wymia<strong>na</strong> war<strong>to</strong>sci<br />
1. (1,2,x,4)<br />
2. (1,2,y,4)<br />
3. (1,2,3,4)<br />
4. (1,2,z,4)<br />
Krok 2 – wymia<strong>na</strong> wek<strong>to</strong>rów war<strong>to</strong>sci<br />
1. (1,2,x,4) 2. (1,2,x,4) 3. (1,2,x,4) 4. (1,2,x,4)<br />
(1,2,y,4) (1,2,y,4) (1,2,y,4) (1,2,y,4)<br />
(a,b,c,d) (e,f,g,h) (1,2,3,4) (i,j,k,l)<br />
(1,2,z,4) (1,2,z,4) (1,2,z,4) (1,2,z,4)<br />
Rysunek 3.1: Problem bizantyjskich generałów. Trzech z czterech generałów<br />
jest lojalnych, jeden jest zdrajcą. (a) Krok 1 - <strong>na</strong>stępuje wymia<strong>na</strong> informacji<br />
o liczebności wojska między każdą z par generałów. (b) Krok 2 - generałowie<br />
wymieniają między sobą wek<strong>to</strong>ry zawierające liczebność całej armii.<br />
wznoszących się <strong>na</strong>d doliną. Ich celem jest ustalenie wielkości niebieskiej armii,<br />
tak by określić, czy jest o<strong>na</strong> silniejsza od armii generała czerwonego, gdyż<br />
jedynie połączony atak może przynieść zwycięstwo. Generałowie mogą komunikować<br />
się między sobą, ale tylko rozłącznie, czyli tylko z jednym w tej samej<br />
chwili, używając niezawodnych ka<strong>na</strong>łów komunikacyjnych. Niestety między generałami<br />
z<strong>na</strong>jduje się jeden zdrajca, który został przekupiony przez czerwonego<br />
generała.<br />
W pierwszym kroku wszyscy k generałowie przesyłają parami <strong>na</strong>wzajem<br />
liczebność swoich armii, tak, że każdy z nich po zakończeniu wymiany otrzymuje<br />
wek<strong>to</strong>r war<strong>to</strong>ści, w którym i-ta ze współrzędnych odpowiada wielości armii i-<br />
tego generała. Jeżeli zażyłoby się tak, iż i-ty z generałów odmawia przesłania<br />
stanu armii w i-tym polu wprowadza się specjalną pustą war<strong>to</strong>ść, np. NULL.<br />
Kolejny krok polega <strong>na</strong> wymianie wek<strong>to</strong>rów między generałami, tak, że ostatecznie<br />
każdy z nich będzie posiadał k − 1 wek<strong>to</strong>rów odebranych oraz jeden<br />
własny. Jeżeli istnieje względ<strong>na</strong> większość takich samych war<strong>to</strong>ści w i-tym<br />
elemencie w każdym z wek<strong>to</strong>rów, <strong>to</strong> generał uz<strong>na</strong>je tą war<strong>to</strong>ść za prawdziwą.<br />
Na rysunku 3.1 przedstawiono sytuację, gdy jeden z generałów próbuje oszukać<br />
pozostałych trzech. Przesyła w pierwszej kolejności do każdego z nich różne<br />
war<strong>to</strong>ści liczebności swojej armii. W drugim kroku przesyła dowolne wek<strong>to</strong>ry,<br />
jako uzyskane po pierwszej turze. Każdy z generałów posiada armię wielkości<br />
odpowiadającej jego numerowi, czyli 1, 2, 3 oraz 4 liczoną w kilo-żołnierzach.<br />
W wyniku działania tego algorytmu każdy z lojalnych generałów posiada <strong>na</strong>stępujący<br />
wek<strong>to</strong>r war<strong>to</strong>ści: (1,2,NULL,4).<br />
Łatwo zauważyć, który z generałów okazał się być nielojalny, jed<strong>na</strong>k gdyby<br />
postępował on konsekwentnie, podając wszystkim lojalnym generałom taką samą,
38 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
niewłaściwą liczebność swojej armii, mógłby ich wprowadzić w błąd. Ten wniosek<br />
jest niezwykle ważny, gdyż pokazuje, że przedstawiony algorytm zezwala <strong>na</strong><br />
uzgodnienie szeregu war<strong>to</strong>ść (ang. byzantine agreement) wspólnie przez grupę<br />
uczestniczącą w komunikacji, <strong>na</strong><strong>to</strong>miast nie daje gwarancji poprawności dla tych<br />
war<strong>to</strong>ści! Milcząco zakładaliśmy, że generałowie z<strong>na</strong>ją liczbę zdrajców, gdyby<br />
było i<strong>na</strong>czej problem stałby się jeszcze trudniejszy do rozwiązania. W takim<br />
przypadku generałowie mogliby polegać jedynie <strong>na</strong> własnej armii, a uzyskanie<br />
informacji o całkowitej liczebności wojsk byłoby niemożliwe.<br />
Gwarant poprawności uzgodnionych war<strong>to</strong>ści moż<strong>na</strong> uzyskać jedynie w takiej<br />
sytuacji, gdy s<strong>to</strong>suje się replikację każdej z nich pomiędzy wielu uczestników i<br />
tylko pod warunkiem, gdy działają oni niezależnie 2 . Zakładając, że atakujący nie<br />
przejmie kontroli <strong>na</strong>d większością uczestników, jak również nie zdarzy się, że<br />
większość uczestników zacznie działać niepoprawnie, uzgodnio<strong>na</strong> war<strong>to</strong>ść będzie<br />
prawidłowa i popraw<strong>na</strong>. Sytuacja taka ma miejsce, gdy uzgadnia<strong>na</strong> war<strong>to</strong>ść jest<br />
tylko jed<strong>na</strong> i dobrze określo<strong>na</strong>, np. jest nią stan usługi, w przeciwieństwie<br />
do przedstawionego przykładu, gdzie tych war<strong>to</strong>ści jest z<strong>na</strong>cznie więcej, bo aż<br />
cztery. Ostatecznie możemy zadać pytanie, jak powinien zostać skonstruowany<br />
algorytm, w którym mamy do czynienia z replikacją typu 1 do wiele oraz wiele<br />
do wiele, czyli gdy wiele różnych war<strong>to</strong>ści rozprowadzanych jest między wiele<br />
replik.<br />
Przypadek, gdy mamy do czynienia tylko z replikacją typu 1dowielerozwiązuje<br />
algorytm odporności <strong>na</strong> błędy <strong>bizantyjskie</strong> BFT (ang. byzantine fault<br />
<strong>to</strong>lerance) [CL99c, CL99a, CL99b, CL00]. Replikacja typu wiele do wiele z<br />
uwzględnieniem zas<strong>to</strong>sowania świadków realizowa<strong>na</strong> jest przez algorytm bezpiecznego<br />
przyczynowego rozgłaszania SC-ABC (ang. secure causal a<strong>to</strong>mic<br />
broadcast) [CKPS01, CKS00]. Oba algorytmy zostały opaten<strong>to</strong>wane 3 .Zarówno<br />
BFT, jak i SC-ABC są uważane przez ich au<strong>to</strong>rów, jako asynchroniczne, chociaż<br />
występują w nich konieczne elementy synchroniczności (patrz Dodatek B). W<br />
przypadku BFT synchronizacja pojawia się w zas<strong>to</strong>sowaniu widoków, pierwszy<br />
raz użytych przez K. Birma<strong>na</strong> (ang. virtual synchrony) [TS01], w pro<strong>to</strong>kole<br />
SC-ABC wykorzystano technikę losowego wyko<strong>na</strong>nia, co zostanie dokładniej<br />
wyjaśnione w dalszej części tego rozdziału.<br />
Całkowicie asynchroniczne algorytmy nie mogą zagwaran<strong>to</strong>wać, że uczestnicy<br />
pro<strong>to</strong>kołu wspólnie dojdą do konsensusu, tak jak <strong>to</strong> zostało udowodnione<br />
przez Fischera i innych [FLP85].<br />
Twierdzenie 1 Nie istnieje taki pro<strong>to</strong>kół asynchronicznego uzgadniania P, który<br />
gwaran<strong>to</strong>wałby całkowitą poprawność, gdy chociaż jeden proces działa błędnie.<br />
2 Dodatkowe repliki częs<strong>to</strong> <strong>na</strong>zwa się świadkami (ang. witness).<br />
3 BFT jest objęty patentem między<strong>na</strong>rodowym (nr US6671821 B1, 2003/12/30), SC-ABC jest<br />
również objęty patentem między<strong>na</strong>rodowym (nr US2002129087 A1).
3.2 Replikacja z uwzględnieniem błędów bizantyjskich 39<br />
Dowód twierdzenia 1 jest niezmiernie ważny i ma podstawowe z<strong>na</strong>czenie<br />
praktyczne, dlatego został zamieszczony w Dodatku B. Wniosek, który płynie z<br />
tego twierdzenia, jest <strong>na</strong>stępujący: nie możemy projek<strong>to</strong>wać algorytmu uzgadniania,<br />
który byłby pozbawiony, <strong>na</strong>wet w <strong>na</strong>jmniejszym s<strong>to</strong>pniu, komunikacji<br />
synchronicznej między uczestnikami, gdyż dopuszczałby możliwość zaistnienia<br />
sytuacji, w której nie zakończyłby on swojego działania.<br />
Twierdzenie 2 Istnieje częściowo poprawny pro<strong>to</strong>kół uzgadniania, w którym<br />
wszystkie poprawnie działające procesy podejmą decyzję, jeżeli tylko stanowią<br />
większość i podczas operacji uzgadniania pozostaną sprawne.<br />
BFT oraz SC-ABC rozwiązują problem uzgadniania w przypadku błędów bizantyjskich<br />
s<strong>to</strong>sując słabsze założenia niż w twierdzeniu 2, dzięki temu możliwe<br />
jest poprawne zakończenie pro<strong>to</strong>kołu <strong>na</strong>wet gdy część uczestników przestanie<br />
odpowiadać w trakcie jego realizacji. Na szczególną uwagę zasługuje algorytm<br />
SC-ABC, który jest prawie całkowicie asynchroniczny, ale może nie zakończyć<br />
poprawnie swojego działania. Przejścia między sta<strong>na</strong>mi w SC-ABC dokonują<br />
się częściowo w losowy sposób, co w z<strong>na</strong>cznej mierze utrudnia atakującemu<br />
złamanie pro<strong>to</strong>kołu jed<strong>na</strong>k teoretycznie zezwala <strong>na</strong> niepoprawne zakończenie<br />
działania.<br />
3.2 Replikacja z uwzględnieniem błędów bizantyjskich<br />
Załóżmy, że grupa replik składa się z n uczestników i dostarcza deterministyczną<br />
usługę u z wewnętrznym stanem s, która zwraca war<strong>to</strong>ść v w zależności od<br />
zlecenia i, v = u(i, s), s oz<strong>na</strong>cza aktualny stan usługi. Usługa działająca w sposób<br />
niedeterministyczny, np. optymalizacja przy użyciu me<strong>to</strong>d heurystycznych<br />
wymagałaby określenia progu zgodności zwracanych odpowiedzi. Ta praca rozpatruje<br />
jedynie usługi deterministyczne. Rozpatrzenie przypadków gdy repliki<br />
zwracają niedeterministyczne odpowiedzi mogłoby stanowić odrębne opracowanie<br />
i nie będzie dalej poruszane. Klient c wysyła zlecenie do wszystkich replik<br />
używając i c , jako parametru wywołania. Klient zbiera odpowiedzi v k od każdego<br />
k-tego uczestnika grupy.<br />
Twierdzenie 3 Jeżeli pośród n replik f jest działających w sposób bizantyjski,<br />
<strong>to</strong> klient c potrzebuje f +1 takich samych odpowiedzi od różnych replik, by<br />
ustalić poprawną zwracaną war<strong>to</strong>ść v dla wywołania usługi u z parametrem i c .
40 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
Dowód. Załóżmy, że wystarczy f odpowiedzi by ustalić v. Wiedząc, że uszkodzonych<br />
replik jest dokładnie f, <strong>to</strong> odebranie f takich samych odpowiedzi jeszcze<br />
nie gwarantuje, że posiadamy prawdziwy wynik wywołania usługi, gdyż<br />
wszystkie f odpowiedzi może być wysłane od niepoprawnie działających replik.<br />
Gdy takich samych odpowiedzi jest f +1<strong>to</strong> wszystkie one są poprawne, gdyż<br />
f +1>f, czyli muszą pochodzić ze zbioru replik działających poprawnie.<br />
<br />
Twierdzenie 4 Jeżeli pośród n replik f jest działających w sposób bizantyjski<br />
oraz f ≤ ⌊ ⌋<br />
n−1 4<br />
, <strong>to</strong> klient c może ustalić poprawną war<strong>to</strong>ść zwracaną v dla<br />
3<br />
wywołania usługi u z parametrem i c .<br />
Dowód. Jeżeli f replik jest niepoprawnie działających, <strong>to</strong> poprawnie działających<br />
replik zostaje n − f. Po<strong>na</strong>d<strong>to</strong> f z replik poprawnie działających, może<br />
zostać uszkodzonych i nie odpowiedzieć <strong>na</strong> żądanie. Korzystając jednocześnie<br />
z twierdzenia 3 mamy n − 2f ≥ f +1, przepisując n−1 ≥ f, <strong>na</strong>stępnie przekształcamy<br />
nierówność jednocześnie gwarantując, że prawa stro<strong>na</strong> zawsze jest<br />
3<br />
całkowita i otrzymujemy ostatecznie f ≤ ⌊ ⌋<br />
n−1<br />
3 .<br />
<br />
3.3 Algorytm BFT<br />
Właściwości wskazane w poprzednim paragrafie posiada algorytm <strong>to</strong>lerancji<br />
uszkodzeń bizantyjskich (ang. byzantine faoult <strong>to</strong>lerance) BFT, opracowany<br />
przez B. Liskov oraz M. Castro z Programming Methodology Group, MIT w<br />
USA 5 [CL99c, CL99a, CL99b, CL00].<br />
Algorytm BFT zapewnia dwie podstawowe właściwości:<br />
(1) Bezpieczeństwo wyko<strong>na</strong>nia (ang. safety). Wszystkie repliki uzgodnią poprawną<br />
sekwencję wyko<strong>na</strong>nia zleceń pomimo błędów.<br />
(2) Żywotność (ang. liveness). Klient ma gwarancję otrzymania odpowiedzi<br />
<strong>na</strong> swoje żądanie w skończonym czasie t
3.3 Algorytm BFT 41<br />
C<br />
0<br />
1<br />
2<br />
pre-prepare prepare commit<br />
3<br />
Rysunek 3.2: Przebieg wyko<strong>na</strong>nia zlecenia przez kilenta c w BFT. Trzy fazy:<br />
pre-prepare, prepare oraz commit. Replika 3 zostaje uszkodzo<strong>na</strong> i nie uczestniczy<br />
w fazie commit oraz nie wysyła odpowiedzi.<br />
Właściwość (1) jest niezależ<strong>na</strong> w BFT od liczby niepoprawnie działających<br />
replik, <strong>na</strong><strong>to</strong>miast (2) zakłada, że przez cały czas życia usługi nie zostanie przekroczony<br />
warunek z tw. 4 f ≤ ⌊ ⌋<br />
n−1<br />
3 postawiony <strong>na</strong> liczbę niepoprawnie działających<br />
replik. Realizacja (1) odbywa się poprzez użycie niezawodnego a<strong>to</strong>mowego<br />
rozgłaszania używając pro<strong>to</strong>kołu trójfazowego zatwierdzania i porządkowania,<br />
<strong>na</strong><strong>to</strong>miast drugi warunek (2) został zapewniony przez użycie mechanizmu widoków<br />
wraz z proaktywnym odzyskiwaniem stanu (ang. proactive state recovery).<br />
BFT jest praktycznym algorytmem, którego podstawową cechą jest pros<strong>to</strong>ta i<br />
<strong>na</strong>cisk <strong>na</strong> mały <strong>na</strong>kład obliczeń.<br />
3.3.1 Założenia algorytmu BFT<br />
System składa się z R replik świadczących usługę u, która zezwala <strong>na</strong> wyko<strong>na</strong>nie<br />
różnych operacji o. Wielu klientów może wysyłać zlecenia do usługi<br />
jednocześnie. Numer repliki głównej wyz<strong>na</strong>czamy jako p = vmod|R|, gdzie<br />
v jest aktualnym numerem widoku.<br />
Repliki są ponumerowane i ∈{1, ..., R} i każda posiada klucz publiczny i<br />
prywatny podpisany przez zaufaną stronę trzecią. Każda para replik i, j, gdzie<br />
i ≠ j posiada dwa klucze symetryczne k ij oraz k ji .Kluczk ij używany jest do<br />
komunikacji w kierunku od i do j, a klucz k ji w kierunku odwrotnym.<br />
Poprzez σi oz<strong>na</strong>czymy wiadomość m podpisaną przez i-tą replikę,<br />
podpis może zostać wyko<strong>na</strong>ny używając MAC (ang. Message Authentication<br />
Code) lub kryp<strong>to</strong>grafji z kluczem publicznym. Skrót wiadomości (ang. message<br />
digest) m oz<strong>na</strong>czymy d = D(m), gdzie D(·) jest jednokierunkową bezkolizyjną<br />
funkcją skrótu zgodną z RFC-2104, np. MD5 lub SHA-1 6 .<br />
6 Zarówno Message Digest 5, jakiSecure Hash Algorithm <strong>na</strong> chwilę obecną podejrzewane są<br />
o możliwość wystąpienia w nich kolizji.
42 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
3.3.2 Działanie algorytmu BFT<br />
Klient c wysyła zlecenie do repliki głównej p w postaci m = < REQEST, o, t, c,<br />
d > σc , gdzie o jest operacją do wyko<strong>na</strong>nia, t z<strong>na</strong>cznikiem czasowym (dowolny<br />
z<strong>na</strong>cznik, który <strong>na</strong>daje klient w celu rozróżnienia odpowiedzi), c identyfika<strong>to</strong>r<br />
klienta, np. adres, d skrót całej wiadomości. Replika głów<strong>na</strong> rozsyła zlecenie do<br />
pozostałych replik. Gdyby klient nie otrzymał odpowiedzi wystarczająco szybko<br />
od którejś z replik lub gdy replika głów<strong>na</strong> nie odpowiada, powinien rozgłosić<br />
zlecenie do wszystkich replik.<br />
Replika głów<strong>na</strong> p s<strong>to</strong>sowa<strong>na</strong> jest do <strong>na</strong>dania identyfika<strong>to</strong>ra zleceniu, tak by<br />
uporządkować wyko<strong>na</strong>nie równoległych wywołań. Po odebraniu zlecenia wykonywany<br />
jest trójfazowy pro<strong>to</strong>kół zatwierdzania, podobny do opisanego w [TS01].<br />
Zas<strong>to</strong>sowanie trójfazowego pro<strong>to</strong>kołu gwarantuje, że zlecenia zostaną wyko<strong>na</strong>ne<br />
zgodnie z kolejnością <strong>na</strong>desłania oraz zapewnia poprawność w przypadku uszkodzenia<br />
repliki głównej. Przykładowe wyko<strong>na</strong>nie algorytmu, gdy jed<strong>na</strong> z replik<br />
zawodzi, pokazano <strong>na</strong> rysunku 3.2.<br />
Kolejnym krokiem w algorytmie jest rozgłoszenie przez replikę główną zlecenia<br />
do pozostałych replik σp , m >, które<br />
rozpoczy<strong>na</strong> fazę przed-przygo<strong>to</strong>wania (ang. pre-prepare) 7 . Zmien<strong>na</strong> v w wiadomości<br />
jest aktualnym numerem widoku, dla którego rozpoczy<strong>na</strong> się wyko<strong>na</strong>nie<br />
pro<strong>to</strong>kół, początkowo v =0, n jest kolejnym numerem sekwencji wyko<strong>na</strong>nia<br />
zlecenia pomiędzy dolnym z<strong>na</strong>cznikiem h oraz górnym z<strong>na</strong>cznikiem H, d jest<br />
skrótem wiadomości m. Z<strong>na</strong>czniki związane są z mechanizmem zatwierdzania<br />
stanu, h oz<strong>na</strong>cza ostatni numer sekwencji wyko<strong>na</strong>nia zlecenia, który został<br />
zatwierdzony. Duży z<strong>na</strong>cznik wyz<strong>na</strong>cza się, jako H = K + h, gdzie K jest<br />
pewną stałą np. 100 lub 200 oz<strong>na</strong>czającą okres zatwierdzania stanu. Szczegóły<br />
dotyczące z<strong>na</strong>czników zostaną omówione w punkcie dotyczącym proaktywnego<br />
odzyskiwania stanu.<br />
W odpowiedzi każda z replik wraz z koordy<strong>na</strong><strong>to</strong>rem rozsyła wiadomość <<br />
PREPARE, v, n, d, i> σi do pozostałych replik. Jeżeli replika zaakcep<strong>to</strong>wała<br />
wiadomość PRE-PREPARE dla widoku v oraz n oraz otrzymała 2f +1 wiadomości<br />
PREPARE , <strong>to</strong> rozsyła do pozostałych replik komunikat < COMMIT,<br />
v, n, d, i> σi . Po otrzymaniu 2f +1odpowiedzi COMMIT od różnych replik<br />
wykonuje zlecenie oraz wysyła odpowiedź do klienta < REPLY, t, i, r> σi .<br />
Podsumowując, przy normalnym działaniu przebieg algorytmu jest <strong>na</strong>stępujący:<br />
1. Klient c wysyła zlecenie m = < REQEST, o, t, c, d> σc do repliki głownej<br />
p.<br />
7 Skeen oraz S<strong>to</strong>nebraker <strong>na</strong>zywają fazę przed-przygo<strong>to</strong>wania, zleceniem głosowania (ang.<br />
vote-request), fazę przygo<strong>to</strong>wania <strong>na</strong><strong>to</strong>miast ozaczają przygo<strong>to</strong>waniem zatwierdzenia (ang.<br />
prepare-commit), ostatnia faza <strong>na</strong>zywa się tak samo [TS01].
3.3 Algorytm BFT 43<br />
2. Replika głów<strong>na</strong> p rozgłasza σp ,m><br />
3. Replika i rozgłasza < PREPARE, v, n, d, i> σi i czeka <strong>na</strong> 2f +1takich<br />
komunikatów uwzględniając własny.<br />
4. Gdy warunek z poprzedniego punku jest spełniony replika i rozsyła komunikat<br />
< COMMIT, v, n, d, i> σi i czeka <strong>na</strong> 2f +1 takich samych<br />
komunikatów od innych replik.<br />
5. Gdy warunek z poprzedniego punku jest spełniony replika i wykonuje<br />
zlecenie oraz wysyła odpowiedź do klienta c postaci < REPLY, t, i, r> σi .<br />
Widoki. Mechanizm widoków v jest związany z wprowadzeniem odporności<br />
<strong>na</strong> uszkodzenie repliki głównej p. Gdy replika głów<strong>na</strong> nie odpowie <strong>na</strong> zlecenie<br />
klienta, a rozgłoszone zlecenie dotrze do innej repliki, <strong>to</strong> replika która odebrała<br />
komunikat wysyła < VIEW-CHANGE, v +1, n, C, P, i> σi . C jest zbiorem<br />
2f +1 punktów kontrolnych potwierdzających poprawność stanu s, aP jest<br />
zbiorem zbiorów zleceń P m przygo<strong>to</strong>wanych przez i o z<strong>na</strong>czniku większym niż<br />
n. Każdy podzbiór P m składa się z wiadomości przed-przygo<strong>to</strong>wania oraz 2f<br />
odpowiadających jej wiadomości przygo<strong>to</strong>wania zgodnych co do v, n oraz m.<br />
Nowa replika głów<strong>na</strong> p po odebraniu 2f komunikatów o zmianie widoku<br />
rozsyła wiadomość < NEW-VIEW, v +1, V, O > σp , gdzie V jest zbiorem<br />
komunikatów zmiany widoku. Zbiór O jest wyz<strong>na</strong>czany <strong>na</strong>stępująco:<br />
1. Replika głów<strong>na</strong> określa dwie war<strong>to</strong>ści min s - numer ostatniego stabilnego<br />
z<strong>na</strong>cznika zatwierdzenia stanu w V oraz max s , <strong>na</strong>jwyższy numer zlecenia<br />
w V.<br />
2. Replika głów<strong>na</strong> przygo<strong>to</strong>wuje nowe wiadomości przed-przygo<strong>to</strong>wania dla<br />
każdego n ∈ (min s ,max s ). Mogą zaistnieć dwa przypadki: (1) istnieje<br />
przy<strong>na</strong>jmniej jeden zbiór w P gdzie wystąpił komunikat zmiany widoku<br />
w V z numerem sekwencji n lub (2) nie ma takiego zbioru. W pierwszym<br />
przypadku replika głów<strong>na</strong> tworzy komunikat < PRE-PREPARE, v +1,<br />
n, d> σp , gdzie d jest skrótem zlecenia o <strong>na</strong>jwiększej sekwencji n w<br />
V. W przeciwnym razie replika głów<strong>na</strong> konstruuje komunikat < PRE-<br />
PREPARE, v+1, n, d null > σp , gdzie d null jest skrótem specjalnego pustego<br />
zlecenia null, które jest obsługiwane przez repliki w taki sam sposób, jak<br />
inne zlecenia, ale nie zmienia stanu. Ta technika ma <strong>na</strong> celu usunięcie<br />
ewentualnych luk.<br />
Jeżeli min s jest większe od ostatniego stabilnego stanu dla p, <strong>to</strong>p zapamiętuje<br />
dowód stabilności dla min s . Repliki zapasowe wykonują zlecenia <strong>na</strong>desłane<br />
przez nową replikę główną dla sekwencji pomiędzy min s oraz max s ,alewysyłają<br />
tylko te odpowiedzi do klientów, które nie zostały im przesłane.
44 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
3.3.3 Optymalizacje zas<strong>to</strong>sowane w BFT<br />
Redukcja komunikacji. W ostatniej fazie działania pro<strong>to</strong>kołu odpowiedź wysyła<strong>na</strong><br />
jest do klienta przez wszystkie repliki. Zasadniczym usprawnieniem jest<br />
wybieranie przez klienta tylko jednej z replik do przesłania odpowiedzi <strong>na</strong> zlecenie,<br />
<strong>na</strong><strong>to</strong>miast reszta replik jedynie wysyła potwierdzenia ze skrótem kryp<strong>to</strong>graficznym<br />
wyniku. Mogłoby się zdarzyć, że odpowiedź jest bardzo duża i<br />
nie da się jej przesłać w pojedynczym komunikacie. W takim wypadku wszystkie<br />
repliki powinny uczestniczyć w wysyłaniu odpowiedzi przesyłając jedynie po<br />
części, tak by klient był w stanie złożyć cały komunikat, moż<strong>na</strong> w tym przypadku<br />
zas<strong>to</strong>sować podobne rozwiązania, jakie oferuje pro<strong>to</strong>kół BitTorrent [Coh03].W<br />
Kolejne usprawnienie zaproponowane przez au<strong>to</strong>rów zezwala <strong>na</strong> wyko<strong>na</strong>nie<br />
zlecenia przez replikę i już po fazie przygo<strong>to</strong>wania i wysłanie odpowiedzi do<br />
klienta. Następnie przesłanie tylko potwierdzenia, lub odmowy, gdyby podczas<br />
tej fazy wystąpiła zmia<strong>na</strong> widoku. W takim przypadku, replika musi cofnąć stan<br />
do tego sprzed wyko<strong>na</strong>nia zlecenia.<br />
Trzecia poprawka dotyczy rozróżnienia operacji modyfikujących stan usługi<br />
od takich, które tego nie robią, czyli tylko do odczytu. Klient rozgłasza do<br />
wszystkich replik operację tylko do odczytu i czeka <strong>na</strong> 2f +1 odpowiedzi.<br />
Replika może przygo<strong>to</strong>wać odpowiedź dla klienta wtedy, gdy jej stan będzie<br />
zatwierdzony, gdyż w innym przypadku klient otrzymałby informację o niespójnym<br />
stanie usługi. Operacja tylko do odczytu nie zakończy się poprawnie, gdy<br />
repliki są zajęte, gdyż inne zlecenia modyfikują stan usługi. W tym przypadku<br />
klient musi ponownie rozgłosić żądanie.<br />
Omijanie kryp<strong>to</strong>grafii z kluczem publicznym. Do potwierdzania wszystkich<br />
wiadomości w BFT s<strong>to</strong>suje się MAC, które wyz<strong>na</strong>cza się jednokierunkową bezkolizyjną<br />
funkcją skrótu <strong>na</strong> konkate<strong>na</strong>cji wiadomości i symetrycznego klucza<br />
k ij . Po<strong>na</strong>d<strong>to</strong> w algorytmie s<strong>to</strong>suje się wek<strong>to</strong>ry MAC <strong>na</strong>desłane przez każdą z<br />
replik, tzw. poświadczenia (ang. authentica<strong>to</strong>rs), który <strong>na</strong> j-tej pozycji zawiera<br />
MAC wiadomości m przez<strong>na</strong>czonej od repliki j. S<strong>to</strong>sowanie MAC zamiast podpisów<br />
jest opłacalne wtedy, gdy liczba replik nie jest duża, jed<strong>na</strong>k gdyby było<br />
i<strong>na</strong>czej podpisy uzyskane przy pomocy technik kryp<strong>to</strong>grafii z kluczem publicznym<br />
byłyby z<strong>na</strong>cznie lepsze i bardziej wydajne, gdyż są weryfikowalne nie tylko<br />
przez uczestników grupy replikującej. Jak pokażemy w <strong>na</strong>stępnym rozdziale,<br />
weryfikacja ma bardzo duże z<strong>na</strong>czenie, gdy repliki przyłączają się i opuszczają<br />
grupę.
3.3 Algorytm BFT 45<br />
3.3.4 Proaktywne odzyskiwanie stanu w BFT<br />
Replika zapisuje do dziennika wszytkie operacje, które wykonuje. Zbiór potwierdzonych<br />
i wyko<strong>na</strong>nych zleceń stanowi o stanie usługi s. Stan s określany<br />
jest jako stabilny, jeżeli jest zatwierdzony. Replika chcąc zatwierdzić stan dla<br />
jakiegoś numeru sekwencji n wysyła komunikat postaci < CHECKPOINT, n,<br />
D(s), i> σi . Zatwierdzenie stanu powinno być przeprowadzane co pewną liczbę<br />
zleceń, w zależności od średniego obciążenia usługi, tak by nie występowało ono<br />
za częs<strong>to</strong>, ale też nie było za rzadkie, gdyż <strong>to</strong> może z<strong>na</strong>cznie wydłużyć operację<br />
zmiany widoku opisaną wcześniej. Jeżeli replika odbierze 2f +1 potwierdzeń, <strong>to</strong><br />
może zatwierdzić stan. Wszystkie wiadomości otrzymane dla niższych numerów<br />
sekwencji od n mogą zostać usunięte z dziennika repliki i.<br />
Proaktywne odzyskiwanie stanu jest procesem, który odświeża stan repliki.<br />
Twórcy algorytmu zakładają, że wszystkie repliki są uruchamiane i <strong>na</strong>dzorowane<br />
przez administra<strong>to</strong>ra systemu. Nie jest bra<strong>na</strong> pod uwagę sytuacja, gdy<br />
replika została uruchomio<strong>na</strong> przez atakującego. Jest <strong>to</strong> poprawne założenie dla<br />
tego przypadku, gdyż jedynie repliki <strong>na</strong>dzorowane mogą rozpocząć proces odzyskiwania<br />
stanu. Ta technika pozwala przywrócić uszkodzoną replikę, która<br />
zachowuje się w sposób bizantyjski, do poprawnego działania. Niestety trudno<br />
jest określić, czy replika działa poprawnie, czy też nie. W związku z powyższym<br />
każda z replik posiada proces <strong>na</strong>dzorujący (ang. watchdog), który co ustalony<br />
interwał rozpoczy<strong>na</strong> kontrolowany restart repliki.<br />
Pro<strong>to</strong>kół estymujący. Faza estymacji ma <strong>na</strong> celu ustalenie, który ostatni numer<br />
sekwencji zleceń repliki uz<strong>na</strong>ją za stabilny. Replika i rozgłasza komunikat <<br />
QUERY-STABLE, i, k> σi , gdzie k jest losową liczbą. Kiedy replika j odbierze<br />
komunikat wysyła odpowiedź < REPLY-STABLE, c, e, i, k> σj i, c jest ostatnim<br />
stabilnym numerem sekwencji, e jest ostatnim numerem sekwencji zlecenia<br />
przygo<strong>to</strong>wanym przez j. Replika i zachowuje <strong>na</strong>jmniejszą war<strong>to</strong>ść c oraz <strong>na</strong>jwiększą<br />
e oraz swoje własne. Następnie szacuje H M = L + c M , gdzie L jest<br />
rozmiarem dziennika, <strong>na</strong><strong>to</strong>miast c M musi być większe od jakiegokolwiek ostatniego<br />
z<strong>na</strong>cznika zatwierdzenia, c M jest taką war<strong>to</strong>ścią otrzymaną od repliki j,<br />
że przy<strong>na</strong>jmniej 2f replik podało c mniejsze bądź równe od c podanego przez<br />
j oraz f replik różnych od j podało war<strong>to</strong>ści e większe bądź równe c M .<br />
Zlecenie odzyskania stanu. Replika i wysyła zlecenie odzyskania stanu <<br />
REQUEST, < RECOVERY, H M >, t, i > σi . Parametr t w wywołaniu musi być<br />
losowym z<strong>na</strong>cznikiem większym od uprzednio wysłanego. Replika j odrzuci<br />
wiadomość z t mniejszym od uprzedniego, jak również taką wiadomość, która<br />
była <strong>na</strong>da<strong>na</strong> przez i w czasie nie większym niż połowa okresu odnowienia repliki.<br />
Takie postępowanie ma <strong>na</strong> celu wykluczenie ataków zablokowania usługi typu<br />
DoS (ang. denial-of-service), który byłby wynikiem całkowitego obciążenia
46 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
grupy zleceniami odnowienia stanu.<br />
Podczas odzyskiwania stanu musi <strong>na</strong>stąpić wymia<strong>na</strong> kluczy, gdyż stare klucze<br />
mogły zostać przechwycone przez atakującego. Odpowiedź zawiera numer<br />
sekwencji zlecenia n R przez co replika może wyz<strong>na</strong>czyć H R = ⌊n R /K⌋×K+L,<br />
<strong>na</strong>stępnie oblicza H = max(H M ,H R ), która <strong>to</strong> war<strong>to</strong>ść jest górnym z<strong>na</strong>cznikiem.<br />
Używając wszystkich zebranych informacji rozpoczy<strong>na</strong> proces pobrania<br />
stanu [CL00] 8 .<br />
Ważnym założeniem jest <strong>to</strong>, by proaktywne odzyskiwanie stanu nie było<br />
realizowane przez więcej jak jedną replikę równolegle (o ile nie wiadomo ze<br />
100% pewnością, że niepoprawnie realizuje zlecenia), gdyż w ten sposób <strong>na</strong>raża<br />
się usługę <strong>na</strong> niepoprawne działanie. Okres w jakim usługa <strong>na</strong>rażo<strong>na</strong> jest <strong>na</strong><br />
załamanie jest równy T v =2T k + T r , gdzie T k oz<strong>na</strong>cza czas wymiany kluczy, T r<br />
jest czasem od załamania repliki do czasu odzyskania przez nią pełnej informacji<br />
o aktualnym stanie usługi [CL00].<br />
Do niewątpliwych zalet BFT <strong>na</strong>leży zaliczyć: łatwą implementację i możliwość<br />
adaptacji do wielu systemów. Z<strong>na</strong>cząca wadą tego algorytmu jest konieczność<br />
wykrywania niepoprawnie działającej repliki głównej, czyli uzależnienie od<br />
czasu odpowiedzi tzw. (ang. failure detec<strong>to</strong>rs), oraz szeregu parametrów, które<br />
muszą być dos<strong>to</strong>sowane do środowiska, w celu zagwaran<strong>to</strong>wania żywotności i<br />
efektywności.<br />
3.4 Algorytm SC-ABC<br />
SC-ABC jest s<strong>to</strong>sem pro<strong>to</strong>kołów używających tzw. kryp<strong>to</strong>grafii progowej, nowoczesnej<br />
techniki kryp<strong>to</strong>graficznej, która bardzo ogólnie zostanie omówio<strong>na</strong><br />
w kolejnym paragrafie tak, by umożliwić zrozumienie sposóbu działania algorytmu.<br />
SC-ABC został opracowany przez grupę badawczą z labora<strong>to</strong>rium IBM<br />
w Zurichu, głównie przez K. Kursawe oraz V. Schoupa. S<strong>to</strong>s pro<strong>to</strong>kołów rozpoczy<strong>na</strong><br />
bi<strong>na</strong>rne <strong>bizantyjskie</strong> uzgadnianie (ang. Bi<strong>na</strong>ry Byzantine Agreement)<br />
BBA, <strong>na</strong>stępnie wielowar<strong>to</strong>ściowe <strong>bizantyjskie</strong> uzgadnianie (ang. Multi-valued<br />
Byzantine Agreement) MBA, a<strong>to</strong>mowe rozgłaszanie (ang. A<strong>to</strong>mic Broadcast)<br />
ABC. Pro<strong>to</strong>kołem <strong>na</strong>jwyższego poziomu jest algorytm bezpiecznego przyczynowego<br />
rozgłaszania (ang. Secure Causal A<strong>to</strong>mic Broadcast) SC-ABC. Pro<strong>to</strong>kół<br />
jest w większym s<strong>to</strong>pniu asynchroniczny niż miało <strong>to</strong> miejsce w BFT, poprzez<br />
zas<strong>to</strong>sowanie elementów losowych, co pociąga za sobą istnienie pewnego niezerowego<br />
prawdopodobieństwa tego, iż pro<strong>to</strong>kół poprawnie nie zakończy działania.<br />
Twórcy algorytmu tłumaczą, że praktycznie żaden pro<strong>to</strong>kół nie gwarantuje<br />
całkowitej poprawności, gdyż zależy od różnych założeń, które w środowisku<br />
usługi.<br />
8 Opis procesu transferu stanu został pominięty, gdyż jego konstrukcja może zależeć od samej
3.4 Algorytm SC-ABC 47<br />
pracy nie zawsze będą spełnione. Według au<strong>to</strong>rów, gdyby realizacja pro<strong>to</strong>kołu<br />
nie przyniosła efektu (nie zakończyła się, lub zakończyła się błędnie), <strong>na</strong>leży<br />
przerwać jego wyko<strong>na</strong>nie i rozpocząć je ponownie, gdyż warunki początkowe<br />
uruchomienia mogą ulec zmianie i poprawne zakończenie stanie się możliwe<br />
[CKPS01].<br />
Założenia ogólne. Ka<strong>na</strong>ł komunikacyjny jest całkowicie zależny od atakującego.<br />
Wszystkie wiadomości są au<strong>to</strong>ryzowane. Złożoność wyko<strong>na</strong>nia poszczególnych<br />
pro<strong>to</strong>kołów w s<strong>to</strong>sie jest probabilistycznie jednostajnie ograniczo<strong>na</strong>.<br />
Definicja. Złożoność pro<strong>to</strong>kołu X <strong>na</strong>zywamy probabilistycznie jednostajnie<br />
ograniczoną, jeżeli dla dowolnego wielomianu T (k) i k ≥ 0, istnieje zaniedbywalnie<br />
mała war<strong>to</strong>ść ɛ(k) taka, która spełnia:<br />
Pr[X(k) >T(k)] ≤ ɛ(k),<br />
czyli, że prawdopodobieństwo tego, iż złożoność wyko<strong>na</strong>nia pro<strong>to</strong>kołu X<br />
będzie większa niż wielomianowa, jest odpowiednio małe. Dla złożenia pro<strong>to</strong>kołów<br />
rozumianego w ten sposób, że jeżeli pro<strong>to</strong>kół X A używa pod-pro<strong>to</strong>kołu<br />
X B i złożoności obu z nich są probabilistycznie jednostajnie ograniczone, złożoność<br />
pro<strong>to</strong>kółu X AB jest również probabilistycznie jednostajnie ograniczo<strong>na</strong> 9 .<br />
To rozumowanie pokazuje, że złożoność probabilistycznego pro<strong>to</strong>kołu SC-ABC<br />
jest zaniedbywalnie większa od złożoności wielomianowej. Au<strong>to</strong>rzy starają się<br />
udowodnić, że pro<strong>to</strong>koły o losowym charakterze długości wyko<strong>na</strong>nia są użyteczne,<br />
jeżeli tylko jesteśmy w stanie zapewnić, że przypadki nieskończenie<br />
długich wyko<strong>na</strong>ń będą zdarzały się pomijalnie rzadko. Oczywiście, czy jest<br />
<strong>to</strong> podejście słuszne, czy nie, jest kwestią dyskusyjną. Zgodzić się moż<strong>na</strong>, że<br />
posiadając informację o tym, jak długo zajmuje średnie wyko<strong>na</strong>nie pro<strong>to</strong>kołu,<br />
możemy przerwać realizację, a <strong>na</strong>stępnie ją ponowić.<br />
Hierarchiczne wywołania. Instancje pro<strong>to</strong>kołu mają unikalne ID, które <strong>na</strong>dawane<br />
jest jednorazowo. Jeżeli uczestnik odbierze komunikat oz<strong>na</strong>czony uprzednio<br />
otrzymanym ID, który jest zleceniem operacji, która już została wyko<strong>na</strong><strong>na</strong>,<br />
<strong>to</strong> komunikat zostanie zignorowany. Pod-pro<strong>to</strong>koły identyfikowane są poprzez<br />
konkate<strong>na</strong>cję ID pro<strong>to</strong>kołu wyższego rzędu oraz unikalnego ID w ramach tego<br />
pod-pro<strong>to</strong>kołu, czyli ID|ID ′ |.... Wiadomości <strong>na</strong>dane przez uczestnika i mogą<br />
być <strong>na</strong>stępującej kategorii:<br />
Wejście - ( ID, in , akcja, typ ) i<br />
9 Szczegóły dotyczące definicji złożoności probabilistycznie jednostajnie ograniczonej dostępne<br />
są w pracy [CKPS01].
48 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
Wyjście - ( ID, out , akcja, typ ) i<br />
Pro<strong>to</strong>kół - ( ID, akcja, ··· ) i<br />
Istnieją dwie ważne akcje w przypadku wiadomości kategorii pro<strong>to</strong>kołu: (1)<br />
open, która otwiera instancję pro<strong>to</strong>kołu, oraz (2) halt, zamykająca wyko<strong>na</strong>nie<br />
instancji pro<strong>to</strong>kołu wskazanego przez ID.<br />
Bizantyjskie uzgadnianie. Pro<strong>to</strong>kół rozpoczy<strong>na</strong> działanie gdy do uczestnika i<br />
zostanie doręczony komunikat ( ID, in, propose, v ) i , gdzie v ∈{0, 1}. Zakończenie<br />
pro<strong>to</strong>kołu dla i-tego uczestnika <strong>na</strong>stępuje gdy <strong>na</strong>da on komunikat (<br />
ID, out, decide, v ) i . W oparciu o przedstawione założenia, bi<strong>na</strong>rne <strong>bizantyjskie</strong><br />
uzgadnianie moż<strong>na</strong> rozumieć jako pro<strong>to</strong>kół spełniający cztery <strong>na</strong>stępujące<br />
postulaty:<br />
Poprawność. Wszyscy poprawnie działający uczestnicy pro<strong>to</strong>kołu jeżeli<br />
rozpoczy<strong>na</strong>ją uzgadnianie podając war<strong>to</strong>ść jako decyzję v, <strong>to</strong> akceptują<br />
war<strong>to</strong>ść v.<br />
Uczciwość. Jeżeli jakiś poprawnie działający uczestnik zaakcep<strong>to</strong>wał v, <strong>to</strong><br />
zakończył działanie pro<strong>to</strong>kołu z war<strong>to</strong>ścią v.<br />
Żywotność.<br />
uzgadnianiu.<br />
Wszyscy poprawnie działający uczestnicy biorą udział w<br />
Wydajność. Pro<strong>to</strong>kół jest probabilistycznie jednostajnie ograniczony.<br />
Pierwszy postulat jest bardzo mocny i nie zezwala <strong>na</strong> początkową niezgodność<br />
co do war<strong>to</strong>ści v zaproponowaną przez uczciwych uczestników. Nie dopuszcza<br />
się do zaistnienia sytuacji, w której jakiś z uczciwych uczestników pro<strong>to</strong>kołu się<br />
pomylił.<br />
3.4.1 Kryp<strong>to</strong>grafia progowa<br />
SC-ABC używa w dużym s<strong>to</strong>pniu nowoczesnych technik kryp<strong>to</strong>graficznych. Jego<br />
szkielet oparty jest <strong>na</strong> mechanizmach kryp<strong>to</strong>grafii progowej. Prosty schemat<br />
kryp<strong>to</strong>grafii progowej z kluczem publicznym przedstawiono <strong>na</strong> rysunku 3.3.<br />
Współdzielenie sekretu. Najłatwiej zrozumieć działanie kryp<strong>to</strong>grafii progowej<br />
<strong>na</strong> przykładzie prostego algorytmu zaproponowanego przez A. Shamira [Sha79].<br />
Celem tego algorytmu jest umożliwienie k z n uczestników zrekonstruowanie<br />
wiadomości (sekretu) D. Jeżeli uczestników będzie mniej niż k <strong>to</strong> nie będą<br />
oni w stanie uzyskać jakiejkolwiek informacji o D. Algorytm używa prostej<br />
interpolacji wielomianem:
3.4 Algorytm SC-ABC 49<br />
Rysunek 3.3: Przykład schematu (2 z 3) kryp<strong>to</strong>grafii progowej z kluczem publicznym.<br />
Klucz publiczny składa się z trzech udziałów. Ta sama wiadomość<br />
szyfrowa<strong>na</strong> jest przez trzech uczestników. Jeden z uczestników gubi szyfrogram,<br />
lub ulega on zniszczeniu. Odszyfrowanie wiadomości przy pomocy klucza<br />
prywatnego <strong>na</strong>dal pozostaje możliwe, gdyż wystarczą do tego pozostałe dwa<br />
szyfrogramy.<br />
q(x) =a 0 + a 1 x + a 2 x 2 + a k−1 x k−1 , a 0 = D<br />
w ciele modulo p, gdzie p jest liczbą pierwszą większą od D oraz n. Współczynniki<br />
wielomianu są wylosowane zgodnie z rozkładem jednostajnym a i ∈ [0,p).<br />
Każda z części sekretu D wyz<strong>na</strong>czo<strong>na</strong> jest w taki sposób, że:<br />
D 1 = q(1),D 2 = q(2) ···,D n = q(n)<br />
Posiadając k z części D wraz z ich identyfika<strong>to</strong>rami, możliwe jest poprzez<br />
interpolację określenie współczynników w q(x), a co za tym idzie obliczenie<br />
D = q(0), które jest sekretem. Pozostaje pokazać co stanie się gdy k<strong>to</strong>ś przechwyci<br />
k − 1 udziałów. Dla każdego D ′ ∈ [0,p) może skonstruować wielomian<br />
q ′ (x), któryspełniaD ′ = q ′ (0) oraz D i = q ′ (i). Z założenia każdy z<br />
tych p wielomianów z jed<strong>na</strong>kowym prawdopodobieństwem, jest poszukiwanym<br />
wielomianem q(x). Zatem, jeżeli p jestdużeorazatakującyniemażadnych<br />
dodatkowych informacji o D, <strong>to</strong> nie będzie w stanie określić właściwego q(x)<br />
s<strong>to</strong>sując inną me<strong>to</strong>dę niż atak brutalny (sprawdzenie wszystkich możliwych war<strong>to</strong>ści).<br />
Ten schemat jest bardzo prosty, jed<strong>na</strong>k wystarczająco dobrze ilustruje<br />
is<strong>to</strong>tę kryp<strong>to</strong>grafii progowej.
50 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
Ogólnie kryp<strong>to</strong>system progowy k z n oz<strong>na</strong>czony (k, n), jest <strong>to</strong> taki schemat<br />
kryp<strong>to</strong>graficzny, w którym do prawidłowego przeprowadzenia operacji wymagane<br />
jest t ≥ k uczestników.<br />
Istnieją różne typy kryp<strong>to</strong>systemów progowych, np. takie które uwzględniają<br />
wagę uczestników, schematy te <strong>na</strong>zywają się ważonymi kryp<strong>to</strong>systemami<br />
progowymi. Algorytm SC-ABC używa trzech schematów progowych: współdzielonego<br />
sekretu, progowego podrzucania monetą (ang. treshold common coin<br />
<strong>to</strong>ssing) oraz progowych podpisów cyfrowych (ang. treshold sig<strong>na</strong>tures).<br />
Współdzielone podrzucanie monetą. Odwzorowanie „podrzucania monetą”<br />
oz<strong>na</strong>czamy przez F : {0, 1} ∗ −→ {0, 1}. Jest <strong>to</strong> takie przekształcenie, które<br />
dowolny ciąg bi<strong>to</strong>wy odwzorowuje <strong>na</strong> 0 lub 1. Progowe podrzucanie monetą<br />
(n, k) polega <strong>na</strong> tym, że przy<strong>na</strong>jmniej k uczestników musi kooperować w celu<br />
określenia zwracanej war<strong>to</strong>ści przez odwzorowanie F . Wejściowy ciąg z<strong>na</strong>ków<br />
jest ciągiem decyzji, który może być losowy, dlatego wynik działania F nie jest<br />
deterministyczny.<br />
Progowe podpisy cyfrowe. Algorytmy szyfrowania z kluczem publicznym zakładają<br />
istnienie pary kluczy: klucza prywatnego oraz klucza publicznego posiadanego<br />
przez każdego z uczestników komunikacji [RSA77, MVO96]. Klucz<br />
prywatny służy do odszyfrowywania wiadomości wcześniej zaszyfrowanej kluczem<br />
publicznym. Klucz publiczny jest jawny. Podpis wykonuje się kluczem<br />
prywatnym, <strong>na</strong><strong>to</strong>miast jego weryfikacja odbywa się za pomocą klucza publicznego<br />
(tzw. klucza weryfikującego). W schemacie (n, k, t) podpisu progowego,<br />
klucz publiczny jest jeden <strong>na</strong><strong>to</strong>miast klucz prywatny rozdzielony jest <strong>na</strong> n udziałów.<br />
Do wygenerowania poprawnego podpisu wiadomości m, potrzeba t ≥ k<br />
uczestników podpisujących tę samą wiadomość m, tak by podpis był weryfikowalny.<br />
Kryp<strong>to</strong>systemy progowe świetnie <strong>na</strong>dają się do zas<strong>to</strong>sowania przy głosowaniach,<br />
gdyż u podstawy ich konstrukcji zakłada się istnienie większości, koniecznej<br />
do poprawnego działania. Główny problem, który pojawia się podczas<br />
s<strong>to</strong>sowania kryp<strong>to</strong>grafii progowej ujawnia się, gdy grupa uczestnicząca w określonym<br />
pro<strong>to</strong>kole zmienia skład.<br />
3.4.2 S<strong>to</strong>s pro<strong>to</strong>kołów SC-ABC<br />
Opis algorytmu zaczniemy od <strong>na</strong>jniższej warstwy dotyczących funkcji rozgłaszania.<br />
Częs<strong>to</strong> wykorzystywanym mechanizmem komunikacji między współpracującymi<br />
procesami jest niezawodne rozgłaszanie (ang. Reliable Broadcast).<br />
Gwarantuje ono, że komunikat zostanie dostarczony do wszystkich uczestników
3.4 Algorytm SC-ABC 51<br />
Secure Causal A<strong>to</strong>mic Broadcast SC-ABC<br />
A<strong>to</strong>mic Broadcast ABC<br />
Multi-valued Byzantine Agreement MBA<br />
Bi<strong>na</strong>ry Byzantine Agreement BBA<br />
Broadcast Primitives<br />
Treshold cryp<strong>to</strong>graphy<br />
Rysunek 3.4: S<strong>to</strong>s pro<strong>to</strong>kołów algorytmu SC-ABC. Warstwa wyższa używa warstwy<br />
niższej w celu osiągnięcia wyniku. S<strong>to</strong>s pro<strong>to</strong>kołów korzysta z podstawowych<br />
mechanizmów rozgłaszania oraz kryp<strong>to</strong>grafii progowej.<br />
komunikacji. Dodatkową właściwością zapewnianą przez niezawodne rozgłaszanie<br />
jest <strong>to</strong>, że wysłany komunikat zostanie dostarczony co <strong>na</strong>jwyżej jeden<br />
raz. W większości przypadków złożoność tej operacji wymaga O(n 2 ) komunikatów,<br />
gdzie n oz<strong>na</strong>cza liczbę uczestników. Usługa niezawodnego rozgłaszania<br />
rozwiązuje uprzednio przedstawiony problem bizantyjskich generałów.<br />
Niekiedy ważne jest, by dało się potwierdzić, iż da<strong>na</strong> wiadomość została<br />
<strong>na</strong>prawdę dostarczo<strong>na</strong> do wszystkich uczestników. Właściwość taką posiada<br />
weryfikowalne rozgłaszanie (ang. Verifable Broadcast). Ogólnie, jeżeli jakiś<br />
uczestnik nie wie, czy <strong>na</strong>leży odebrać wiadomość m, <strong>to</strong> inny uczestnik może<br />
wysłać dla niego potwierdzenie, które określi, że wiadomość m powin<strong>na</strong> być<br />
dostarczo<strong>na</strong>.<br />
Nie zawsze zagwaran<strong>to</strong>wanie, że wszystkie wiadomości zostały dostarczone,<br />
jest możliwe. Może zdarzyć się, że któryś z uczestników nie jest osiągalny<br />
podczas wysyłania komunikatu. Pro<strong>to</strong>kół, który zezwala by wiadomość została<br />
doręczo<strong>na</strong> w innym terminie <strong>na</strong>zywa się spójnym rozgłaszaniem (ang. Consistent<br />
Broadcast). Złożenie opisanego poprzedniego pro<strong>to</strong>kołu i opisanego w<br />
tym akapicie prowadzi do weryfikowalnego spójnego rozgłaszania (ang. Verifable<br />
Consistent Broadcast) VCBC, który zakłada weryfikację dostarczenia wiadomości<br />
oraz zezwala <strong>na</strong> <strong>to</strong> by nie wszystkie wiadomości były odebrane w tym samym<br />
czasie przez wszystkich uczestników grupy.<br />
Kolejnymi cegiełkami użytymi do konstrukcji algorytmu SC-ABC jest potwierdzone<br />
<strong>bizantyjskie</strong> uzgadnianie (ang. Validated Byzantine Agreement)VBA,<br />
oraz a<strong>to</strong>mowe rozgłaszanie (ang. A<strong>to</strong>mic Broadcast) ABC.<br />
Bi<strong>na</strong>rne <strong>bizantyjskie</strong> uzgadnianie (ang. Bi<strong>na</strong>ry Byzantine Agreement) jest<br />
pro<strong>to</strong>kołem potwierdzonego <strong>bizantyjskie</strong>go uzgadniania, w którym zbiór możliwych<br />
do uzgodnienia war<strong>to</strong>ści ogranicza się tylko do v ∈{0, 1}. Wielowar<strong>to</strong>ściowe<br />
<strong>bizantyjskie</strong> uzgadnianie (ang. Multi-valued Byzantine Agreement) realizuje<br />
pro<strong>to</strong>kół potwierdzonego <strong>bizantyjskie</strong>go uzgadniania. Gdy ograniczymy
52 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
war<strong>to</strong>ści możliwe do uzgodnienia przez wielowar<strong>to</strong>ściowe <strong>bizantyjskie</strong> uzgadnianie<br />
tylko do v ∈{0, 1} au<strong>to</strong>matycznie uzyskujemy pro<strong>to</strong>kół bi<strong>na</strong>rnego <strong>bizantyjskie</strong>go<br />
uzgadniania. Rozróżnienie <strong>na</strong> te dwa przypadki jest uzasadnione, gdyż<br />
bi<strong>na</strong>rne <strong>bizantyjskie</strong> uzgadnianie s<strong>to</strong>sowane jest wtedy, gdy np. grupa ma <strong>na</strong><br />
celu zatwierdzenie transakcji. Przejdę teraz do omówienia po kolei <strong>na</strong>jważniejszych<br />
elementów użytych w algorytmie SC-ABC.<br />
Założenia. Przyjmiemy, że S będzie oz<strong>na</strong>czać kryp<strong>to</strong>system progowego podpisu<br />
cyfrowego, <strong>na</strong><strong>to</strong>miast E będzie progowym schematem szyfrującym. S 1 oz<strong>na</strong>cza<br />
schemat podwójnego progowego podpisu cyfrowego typu (n, ⌈ ⌉<br />
n+t+1<br />
2 ,t). Ogólnie<br />
schemat (n, κ, t) oz<strong>na</strong>cza, taki kryp<strong>to</strong>system, w którym do wyko<strong>na</strong>nia operacji<br />
potrzeba t
3.4 Algorytm SC-ABC 53<br />
będzie podejmował l, a <strong>na</strong>stępnie rozesłać podpis do wszystkich uczestników i<br />
oczekiwać <strong>na</strong> ⌈ ⌉<br />
n+t+1<br />
2 podpisów od innych uczestników, wtedy każdy w grupie<br />
staje się <strong>na</strong>dawcą wiadomości m. Innym podejściem jest założenie, że uczestnicy<br />
będą czekali, aż rozsyłający znowu zacznie odpowiadać, ale <strong>to</strong> może w<br />
ogóle nie <strong>na</strong>stąpić.<br />
Pro<strong>to</strong>kół 3.5.2. VBA ma <strong>na</strong> celu ustalenie zaproponowanej war<strong>to</strong>ści wspólnie<br />
przez grupę uczestników. Pro<strong>to</strong>kół rozpoczy<strong>na</strong> komunikat ( ID, v-propose, w, π<br />
) l , <strong>na</strong> który uczestnik odpowiada rozsyłając za pomocą VCBC odpowiedź v-echo<br />
wraz z proponowanymi war<strong>to</strong>ściami w oraz π. Nadawca oczekuje <strong>na</strong> n − t propozycji<br />
rozgłoszonych w ten sam sposób od różnych j, które spełniają predykat<br />
Q ID . Q ID (w a ,π a ) jest zbiorem możliwych w a i π a , które są poprawne. Forma,<br />
wjakiejQ ID jest zrealizowane, jest dowol<strong>na</strong>, np. może <strong>to</strong> być zestaw reguł.<br />
Q ID musi być ogólnie z<strong>na</strong>ne, tak by każdy z uczestników mógł przeprowadzić<br />
weryfikację. Uczestnik i buduje tablicę potwierdzeń, gdzie c j =1, gdy j-ty<br />
uczestnik <strong>na</strong>desłał poprawne w j , <strong>na</strong>stępnie rozgłasza ją do pozostałych uczestników.<br />
Odebranie n − t tablic C j , w których przy<strong>na</strong>jmniej n − t wpisów jest<br />
równych 1, stanowi potwierdzenie, że większość uczestników wysłała poprawne<br />
propozycje. Za pomocą progowego podrzucania monetą zostaje wygenerowane<br />
losowe ziarno S składające się z t +1 udziałów, które służy do utworzenia<br />
permutacji Π. W pętli odbywa się głosowanie według a ←− Π(l) dotyczące<br />
war<strong>to</strong>ści w a . Gdy decyzja zostanie podjęta (⊥ również jest dopuszczalną decyzją),<br />
i zakańcza pro<strong>to</strong>kół.<br />
Uwagi. W pro<strong>to</strong>kole VBA użyta jest randomizacja. Ta technika została zas<strong>to</strong>sowa<strong>na</strong>,<br />
by uniemożliwić atakującemu przewidzenie, w jakiej kolejności będą<br />
podawane war<strong>to</strong>ści w j do uzgodnienia. W ten sposób stara się uniknąć tego, by<br />
atakujący w momencie uzgadniania war<strong>to</strong>ści, do niektórych uczestników wysłał<br />
propozycje korzystniejsze dla niego.<br />
Pro<strong>to</strong>kół 3.5.3. ABC jest pierwszym pro<strong>to</strong>kołem, który moż<strong>na</strong> <strong>na</strong>zwać pro<strong>to</strong>kołem<br />
wysokiego poziomu. Każdy z uczestników utrzymuje kolejkę q typu FIFO,<br />
wiadomości do dostarczenia oraz zbiór d już dostarczonych wiadomości. Po<br />
odebraniu wiadomości ( ID, in, a-broadcast, m ) m zostaje wstawione <strong>na</strong> koniec<br />
q, jeżeli m nie jest już w q. W nieskończonej pętli, której każdy przebieg<br />
oz<strong>na</strong>czany jest jako runda r, uczestnik odbiera nową wiadomość lub obsługuje<br />
wiadomości już zgromadzone w kolejce. Gdy zostanie odebra<strong>na</strong> nowa wiadomość<br />
a-queue w ←− w l , która nie z<strong>na</strong>jduje się w d, czyli nie jest dostarczo<strong>na</strong><br />
oraz σ l jest poprawnym podpisem dla w l , <strong>to</strong> zostaje o<strong>na</strong> obsłużo<strong>na</strong>. W przypadku<br />
gdy q nie jest pusta, <strong>to</strong> pierwsza wiadomość z kolejki wysyłkowej będzie<br />
rozesła<strong>na</strong> do wszystkich uczestników. Po <strong>na</strong>daniu komunikatu i czeka <strong>na</strong> n − t
54 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
wiadomości a-queue dla tej samej rundy r. Z otrzymanych odpowiedzi konstrułowany<br />
jest wek<strong>to</strong>r W i wek<strong>to</strong>rem podpisów S, dla którego uruchamiany jest<br />
pro<strong>to</strong>kół wielowar<strong>to</strong>ściowego <strong>bizantyjskie</strong>go uzgadniania v-propose. War<strong>to</strong>ści<br />
oz<strong>na</strong>czone w wek<strong>to</strong>rze V [j] =1rozgłaszane są jako a-delivered ipootrzymaniu<br />
potwierdzenia trafiają do d isąusuwanezq.<br />
Uwagi. A<strong>to</strong>mowe rozgłaszanie wprowadza porządek odbioru dla <strong>na</strong>dawanych komunikatów<br />
gwarantując, że nie dojdzie do sytuacji, że komunikaty przez jednego<br />
użytkownika zostaną odebrane w innej kolejności niż przez innych uczestników.<br />
Bizantyjskie uzgadnianie jest techniką, która pozwala ustalić kolejność <strong>na</strong>dejścia<br />
komunikatów przez użytkowników dla danej rundy r oraz gwarantuje, że wiadomość<br />
zostanie dostarczo<strong>na</strong> do wszystkich poprawnie działających uczestników,<br />
bądź do żadnego z nich.<br />
3.4.3 Działanie algorytmu SC-ABC<br />
SC-ABC rozpoczy<strong>na</strong> działanie po odebraniu przez i wiadomości ( ID, in, s-<br />
broadcast, c ), która zostaje rozgłoszo<strong>na</strong> do wszystkich uczestników, używając<br />
komunikatu a-broadcast pro<strong>to</strong>kołu ABC. Wiadomość c jest zaszyfrowa<strong>na</strong> E 1<br />
kryp<strong>to</strong>systemem progowym (n, t +1)tak, że zebranie t +1udziałów odszyfrowujących<br />
δ pozwala ją odszyfrować. Po odszyfrowaniu wiadomości c zostaje<br />
wysłanie potwierdzenie do reszty uczestników. Replikacja usługi przy użyciu<br />
SC-ABC obywa się wykonując <strong>na</strong>stępujące kroki:<br />
1. Klient wysyła zlecenie c, do jakiejkolwiek z replik.<br />
2. Replika rozgłasza c używając komunikatu s-broadcast, tak, że po odebraniu<br />
t +1udziałów ρ j odszyfrowuje zlecenie m zawarte w szyfrogramie c<br />
i je wykonuje.<br />
3. Replika rozgłasza stan s do innych replik używając komunikatu v-propose.<br />
Gdy stan s zostanie ustalony, jest on oz<strong>na</strong>czany przez replikę, jako stabilny.<br />
Pro<strong>to</strong>kół bezpiecznego a<strong>to</strong>mowego rozgłaszania gwarantuje tajność wiadomości,<br />
gdyż dopiero potwierdzenie przez t+1 uczestników pozwala odszyfrować<br />
<strong>na</strong>dany komunikat. Kroki wykonywane przez pro<strong>to</strong>kół <strong>na</strong>jwyższego poziomu są<br />
oczywiste, dlatego prawdziwa trudność leży w zrozumieniu działania pro<strong>to</strong>kółów<br />
niższego rzędu.
3.5 Podsumowanie 55<br />
3.5 Podsumowanie<br />
W tym rozdziale przedstawiłem dwa podejścia do rozwiązania problemu replikacji<br />
odpornej <strong>na</strong> błędy <strong>bizantyjskie</strong>. Oba opisane algorytmy uzależnione są od<br />
technik kryp<strong>to</strong>graficznych. Algorytm BFT jest mocno ukierunkowany <strong>na</strong> rozwiązanie<br />
zadania replikacji usługi i jego działanie sprowadza się do rozwiązania<br />
podstawowych problemów spowodowanych niepoprawnym działaniem repliki.<br />
SC-ABC ma bardzo dobre właściwości ze względu <strong>na</strong> modularną budowę, ale<br />
nie precyzuje, jak uczestnicy mają postępować w przypadku załamania (rozpadu)<br />
grupy replik. SC-ABC lepiej radzi sobie z uporządkowaniem i bezpieczeństwem<br />
<strong>na</strong>dawanych wiadomości używając kryp<strong>to</strong>grafii progowej, ale przypłaca <strong>to</strong> brakiem<br />
możliwości rekonfiguracji składu grupy. Wadą obydwu algorytmów jest<br />
brak jednoz<strong>na</strong>cznej reakcji <strong>na</strong> sytuację, gdy replika całkowicie opuszcza grupę<br />
i <strong>na</strong>leżałoby ją wykluczyć z dalszej komunikacji oraz włączenie nowej repliki.<br />
Oba przypadki są podstawowym i <strong>na</strong>jczęściej spotykanym zachowaniem replik w<br />
rozproszonych tablicach z kodowaniem mieszającym implemen<strong>to</strong>wanych <strong>na</strong> bazie<br />
systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Wynika z tego, że potrzebne są algorytmy, które w<br />
łatwy sposób zaradzą tym problemom i jednocześnie będą wystarczająco proste<br />
i efektywne, by móc zas<strong>to</strong>sować je w środowisku całkowicie rozproszonym.
56 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
Pro<strong>to</strong>kół 3.5.1: Verifable Consistent Broadcast - VCBC<br />
dla uczestnika P i oraz z<strong>na</strong>cznika ID.j.s<br />
ROZPOCZĘCIE:<br />
¯m ←⊥;¯μ ←⊥<br />
W d ←∅; r d ← 0 (d ∈{0, 1} k′ )<br />
PO ODEBRANIU WIADOMOŚCI ( ID.j.s, in, c-broadcast, m ):<br />
send ( ID.j.s, c-send, m ) i<br />
PO ODEBRANIU WIADOMOŚCI ( ID.j.s, c-send, m ) l :<br />
if j = l ⎧and ¯m = ⊥<br />
⎪⎨ ¯m ← m<br />
then oblicz udział ν podpisu S 1 dla ( ID.j.s, c-ready, H(m) ) i<br />
⎪⎩ send ( ID.j.s, c-ready, m, ν ) i do P j<br />
PO ODEBRANIU WIADOMOŚCI ( ID.j.s, c-ready, d, ν l ) l :<br />
if i = j and ν l jest poprawnym udziałem w S<br />
⎧<br />
1<br />
W d ← W d ∪{ν l }<br />
⎪⎨<br />
r d ← r d +1<br />
then if r d = ⌈ ⌉<br />
n+t+1<br />
{ 2<br />
scal udziały w Wd w jeden S<br />
⎪⎩ then<br />
1 podpis progowy μ<br />
send ( ID.j.s, c-fi<strong>na</strong>l, d, μ ) i do wszystkich P<br />
PO ODEBRANIU WIADOMOŚCI ( ID.j.s, c-fi<strong>na</strong>l, d, ν ) j :<br />
if H(¯m) =d and ¯μ = ⊥ jest poprawnym podpisem S 1<br />
{¯μ ← μ<br />
then<br />
zakończ ( ID.j.s, out, c-deliver, d, ¯m ) i<br />
Realizacja weryfikacji<br />
PO ODEBRANIU WIADOMOŚCI ( ID.j.s, c-request ) l :<br />
if ¯μ ≠ ⊥<br />
then send ( ID.j.s, c-answer, ¯m, ¯μ ) i do P l<br />
PO ODEBRANIU WIADOMOŚCI ( ID.j.s, c-answer, m, μ ) l :<br />
if ¯μ ≠ ⊥ and μ<br />
jest poprawnym<br />
⎧<br />
podpisem S 1 dla ( ID.j.s, c-ready, H(m) ) l<br />
⎪⎨ ¯μ ← μ<br />
then ¯m ← m<br />
⎪⎩ zakończ ( ID.j.s, out, c-deliver, d, ¯m ) i
3.5 Podsumowanie 57<br />
Pro<strong>to</strong>kół 3.5.2: Validated Byzantine Agreement - VBA<br />
dla uczestnika P i , z<strong>na</strong>cznika ID oraz predykatu Q ID<br />
ISTNIEJE PREDYKAT V ID|a (v, ρ):<br />
V ID|a (v, ρ) ≡ (v =0)or (v =1and ρ spełnia c-broadcast<br />
dla wiadomości ( v-echo, w a , π a ) oz<strong>na</strong>czonej ID.a.0 tak, że<br />
Q ID (w a ,π a ) jest spełnione)<br />
PO ODEBRANIU WIADOMOŚCI ( ID, in, v-propose, w, π ):<br />
c-broadcast ( v-echo, w , π ) ozaczone ID|vcbc.i.0<br />
w j ←⊥; π j ←⊥ (1 ≤ j ≤ n)<br />
wait for n − t wiadomości ( v-echo, w j , π j )<br />
c-delivered oz<strong>na</strong>czonych ID|vcbc.j.0 od różnych P j<br />
takich,<br />
{<br />
że spełnione jest Q ID (w j ,π j )<br />
1 jeżeli wj ≠ ⊥<br />
c j ←<br />
(1 ≤ j ≤ n)<br />
0 w innym wypadku<br />
C ← [c 1 , ···,c n ]<br />
c-broadcast ( v-commit, C ) i oz<strong>na</strong>czone ID|vcbc.i.0<br />
C j ←⊥ (1 ≤ j ≤ n)<br />
wait for n − t wiadomości ( v-commit, C j ) j<br />
c-delivered oz<strong>na</strong>czonych ID|vcbc.j.0<br />
takich, że przy<strong>na</strong>jmniej n − t wpisów w C j =1<br />
wygeneruj udział γ w progowym podrzucaniu monetą oz<strong>na</strong>czoną ID|vba<br />
send( ID, v-coin, γ ) i do wszystkich P<br />
wait for t +1wiadomości zawierających udziały w ID|vba<br />
scal udziały by otrzymać S = F (ID|vba) ∈{0, 1} k′′<br />
wybierz losową permutację Π używając genera<strong>to</strong>ra G zziarnemS<br />
l ← 0<br />
repeat<br />
l ← l +1;a ← Π(l)<br />
if w a = ⊥<br />
then<br />
{<br />
send ( ID, v-vote, a, 0, ⊥ ) i do wszystkich P<br />
niech ρ jest wiadomością c-broadcast oz<strong>na</strong>czoną ID|vcbc.a.0<br />
else<br />
send ( ID, v-vote, a, 1, ρ ) i do wszystkich P<br />
u j ←⊥; r j ←⊥ (1 ≤ j ≤ n)<br />
wait for n − t wiadomości ( ID, v-vote, a, u j , ρ j ) j od różnych P j<br />
takich, że V ID|a jest spełnione oraz C j [a] =0gdy u j =0<br />
if ∃ u j =1<br />
then v ← 1; ρ ← ρ j<br />
else v ← 0; ρ ←⊥<br />
zaproponuj v potwierdzone przez ρ dla BBA w stronę 1 z V ID|a<br />
wait for ustalenie war<strong>to</strong>ści b potwierdzonej przez σ dla ID|a<br />
until b =1if w a = ⊥<br />
{<br />
użyj σ do zakończenia c-broadcast oz<strong>na</strong>czonego ID|vcbc.a.0<br />
then<br />
oraz c-deliver (ID, v-echo, w a , π a )<br />
zakończ ( ID, out, v-decide, w a , π a ) i , halt
58 Rozdział 3. Bezpieczne <strong>bizantyjskie</strong> uzgadnianie<br />
Pro<strong>to</strong>kół 3.5.3: A<strong>to</strong>mic Broadcast - ABC<br />
dla uczestnika P i oraz z<strong>na</strong>cznika ID<br />
ISTNIEJE PREDYKAT Q ID|abc.r :<br />
Q ID|abc.r ([w 1 , ···,w n ], [σ 1 , ···,σ n ]) ≡<br />
dla przy<strong>na</strong>jmniej n − t różnych j, σ j jest poprawnym podpisem S<br />
P j dla ( ID, a-queue, r, j, w j ) j<br />
ROZPOCZĘCIE :<br />
q ← [] kolejka FIFO dla wiadomości a-broadcast<br />
d ←∅ zbiór wiadomości a-delivered<br />
r ← 0 bieżąca runda<br />
PO ODEBRANIU WIADOMOŚCI ( ID, in, a-broadcast, m ):<br />
if m/∈ d and m/∈ q<br />
then append(q, m)<br />
ZAWSZE:<br />
w j ←⊥; σ j ←⊥ (1 ≤ j ≤ n)<br />
wait for q ≠[] or odebrano wiadomość ( ID,a-queue,r,l,w l , σ l ) l<br />
taką, że w l /∈ d oraz σ l jest poprawnym podpisem od P l<br />
if q ≠[]<br />
then w ← first(q)<br />
else w ← w l<br />
wyz<strong>na</strong>cz podpis σ dla ( ID,a-queue,r,i,w ) i<br />
send ( ID,a-queue,r,i,w, σ ) i do wszystkich P<br />
wait for n − twiadomości ( ID,a-queue,r,j,w j , σ j ) j ,<br />
takich, że σ j jest poprawnym podpisem od P j<br />
W ← [w 1 , ···,w n ]; S ← [σ 1 , ···,σ n ]<br />
v-propose W potwierdzone przez S<br />
oz<strong>na</strong>czone ID|abc.r z predykatem Q ID|abc.r<br />
wait for zakończenie VBA z V =[v 1 , ···,v n ] oz<strong>na</strong>czonego ID|abc.r<br />
b ← ⋃ n<br />
j=1 v j<br />
for m ∈ (b \ d) w uporządkowany sposób<br />
⎧<br />
zakończ ( ID,out,a-deliver,m) i<br />
⎪⎨ wait for potwierdzenie dla m<br />
do<br />
d ← d ∪{m}<br />
⎪⎩<br />
remove(q, m)<br />
r ← r +1
3.5 Podsumowanie 59<br />
Pro<strong>to</strong>kół 3.5.4: Secure Causal A<strong>to</strong>mic Broadcast - SC-ABC<br />
dla uczestnika P i oraz z<strong>na</strong>cznika ID<br />
ROZPOCZĘCIE :<br />
otwórz ka<strong>na</strong>ł dla a<strong>to</strong>mowego rozgłaszania ID|scabc<br />
PO ODEBRANIU WIADOMOŚCI ( ID, in, s-broadcast, c ):<br />
a-broadcast c ze z<strong>na</strong>cznikiem ID| scabc<br />
ZAWSZE:<br />
wait for kolejną wiadomość c a-deliver ze z<strong>na</strong>cznikiem ID|scabc<br />
oblicz E 1 udział δ odszyfrowujący dla c oz<strong>na</strong>czony ID<br />
zakończ ( ID, out, s-schedule, c ) i<br />
send ( ID, s-decrypt, c, δ ) i do wszystkich P<br />
δ j ←⊥ (1 ≤ j ≤ n)<br />
wait for t +1wiadomości ( ID, s-decrypt, c, δ j ) j od różnych j<br />
zawierających poprawny udział odszyfrowujący dla c oz<strong>na</strong>czony ID<br />
scal wszystkie udziały δ 1 , ···,δ n by uzyskać wiadomość m<br />
zakończ ( ID, out, s-reveal, m ) i<br />
wait for <strong>na</strong> potwierdzenie<br />
zatwierdź ostatnią wiadomość a-delivered oz<strong>na</strong>czoną ID|scabc
Rozdział 4<br />
Tolerowanie bizantyjskich<br />
uszkodzeń<br />
Trudno jest spełnić wymagania przedstawionych w poprzednim rozdziale algorytmów,<br />
ale trudno też nie docenić praktycznego podejścia prezen<strong>to</strong>wanego w<br />
BFT oraz matematycznej poprawności SC-ABC. Naturalnym sposobem postępowania<br />
byłoby połączenie obu pomysłów, tak by sprostać wymaganiom, które<br />
stawiają systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Chodzi przede wszystkim o dużą dy<strong>na</strong>mikę zmian<br />
struktury systemu i brak wzajemnego zaufania współpracujących węzłów.<br />
W tym rozdziale przedstawiłem projekt algorytmu <strong>to</strong>lerowania bizantyjskich<br />
uszkodzeń w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> opracowany w ramach pracy magisterskiej.<br />
W pierwszej kolejności umieszczono opis algorytmu <strong>na</strong>iwnego. Zostały przedstawione<br />
wymagania i założenia projek<strong>to</strong>we. Opisano pierwszą wersję pro<strong>to</strong>kołu,<br />
tzw. zachłanną, by potem przejść do wersji optymistycznej 1 . W <strong>na</strong>stępnej kolejności<br />
zostały opisane założenia i właściwości jakie spełnia zaproponowany<br />
algorytm oraz sposóby utworzenia grupy replik, co zostało pominięte przez au<strong>to</strong>rów<br />
algorytmów BFT i SC-ABC. W dalszej części rozdziału przedstawiłem<br />
pro<strong>to</strong>kół wyko<strong>na</strong>nia zleceń zbudowany <strong>na</strong> bazie uzgadniania wielowar<strong>to</strong>ściowego,<br />
takiego samego jak w BFT. Pokazałem też prostą technikę uzgadniania<br />
stanu wraz ze sterowaniem częs<strong>to</strong>ścią wyko<strong>na</strong>nia migawek. Na koniec zostały<br />
opisane modyfikacje podstawowego algorytmu, które prowadzą do jego wersji<br />
optymistycznej.<br />
1 Zarówno BFT, jak i SC-ABC posiadają wersje optymistyczne, które działają przy słabszych<br />
założeniach. Gdy pro<strong>to</strong>kół optymistyczny zawodzi, s<strong>to</strong>suje się wersję zachłanną<br />
[CL99c, CKPS01].
62 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
4.1 Algorytm <strong>na</strong>iwny<br />
W poprzednim rozdziale z<strong>na</strong>lazł się opis dwóch bardzo skomplikowanych algorytmów<br />
<strong>to</strong>lerowania bizantyjskich uszkodzeń w grupie replik. Rozwiązania te<br />
są kompletne i <strong>na</strong>dają się do praktycznego zas<strong>to</strong>sowania, jed<strong>na</strong>k w wielu przypadkach<br />
będą trudne do implementacji. Pewien s<strong>to</strong>pień <strong>to</strong>lerancji <strong>bizantyjskie</strong>go<br />
zachowania przy bardzo restrykcyjnych założeniach moż<strong>na</strong> uzyskać s<strong>to</strong>sując algorytm<br />
uproszczony (<strong>na</strong>iwny):<br />
• Klient tworzy zlecenie i c , a <strong>na</strong>stępnie wyszukuje wszystkie z<strong>na</strong>ne mu repliki<br />
świadczące usługę u i zleca wyko<strong>na</strong>nie i c przez każdą z nich.<br />
• Po odebraniu f +1 takich samych odpowiedzi v zwróconych przez repliki,<br />
klient kończy wyko<strong>na</strong>nie, przyjmując v = u(i c ).<br />
• Jeżeli takich samych odpowiedzi jest mniej niż f +1, <strong>to</strong> doszło do załamania<br />
usługi lub liczba replik jest n
4.2 Założenia projek<strong>to</strong>we 63<br />
(a)<br />
(b)<br />
Rysunek 4.1: Algorytm <strong>na</strong>iwny. (a) Klient bezpośrednio rozsyła zlecenia do<br />
replik. (b) Wielu klientów używa pośrednika w celu wysłania zleceń.<br />
BFT, <strong>na</strong><strong>to</strong>miast decentralizacja i techniki kryp<strong>to</strong>graficzne prowadzą do algorytmu<br />
SC-ABC. Okazuje się, że możliwym jest osiągnięcie pośredniego schematu<br />
działania, który nie będzie zakładał istnienia elementu centralnego, co jest<br />
niewskazane w <strong>systemach</strong> luźno powiązanych (np. <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>) i który będzie<br />
s<strong>to</strong>sunkowo elastyczny ze względu <strong>na</strong> zarządzanie składem grupy replik.<br />
4.2 Założenia projek<strong>to</strong>we<br />
W skład grupy komunikacyjnej wchodzi k replik, gdzie k ≥ 3f +1, f oz<strong>na</strong>cza<br />
liczbę replik działających w sposób bizantyjski, tak jak zostało <strong>to</strong> zdefiniowane<br />
w poprzednim rozdziale. Każda z replik jest ponumerowa<strong>na</strong> 2 i ∈{0, ..., k}. Replika<br />
i posiada klucze symetryczne używane do komunikacji z każdą inną repliką<br />
wchodzącą w skład grupy sk ij ,i∈{0, ..., k}, i≠ j oraz parę kluczy: klucz publiczny<br />
pk i , klucz prywatny sk i . Repliki działają niezależnie i żad<strong>na</strong> z replik nie<br />
jest wyróżnio<strong>na</strong> jako replika głów<strong>na</strong>. Wiadomość wysyłaną przez replikę oz<strong>na</strong>czymy,<br />
podobnie jak w przypadku BFT, przez σi , gdzie σ i oz<strong>na</strong>cza podpis<br />
wyko<strong>na</strong>ny przy użyciu funkcji skrótu zainicjowanej kluczem repliki i lub kluczem<br />
prywatnym. Skrót kryp<strong>to</strong>graficzny wiadomości m będzie oz<strong>na</strong>czany przez<br />
H(m). Zakładamy iż unikamy kryp<strong>to</strong>grafii z kluczem publicznym, zatem w domyśle<br />
podpis i jest wyko<strong>na</strong>ny przy użyciu odpowiedniego klucza symetrycznego<br />
k ij współdzielonego z repliką j, do której zostanie wysła<strong>na</strong> wiadomość.<br />
Pro<strong>to</strong>kół musi spełniać <strong>na</strong>stępujące wymagania:<br />
• Bezpieczeństwo wyko<strong>na</strong>nia (ang. safety) - błędy wyko<strong>na</strong>nia, bądź uszkodzenia<br />
nie mogą powodować wstrzymania pracy grupy replik.<br />
2 Numerowanie replik wprowadzone jest dla ułatwienia opisu algorytmu. W praktycznej<br />
realizacji wymagane jest tylko, by repliki były w stanie odróżnić siebie <strong>na</strong>wzajem.
64 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
• Żywotność (ang. liveness) - zlecone operacje zostaną wyko<strong>na</strong>ne w skończonym<br />
czasie t
4.2 Założenia projek<strong>to</strong>we 65<br />
• Poczta elektronicz<strong>na</strong> (wielu piszących, jeden czytający). Obiektem jest<br />
skrzynka pocz<strong>to</strong>wa. Wystarczy, że dostęp do skrzynki będzie realizowany z<br />
zachowaniem rozłączności operacji wykonywanych przez różnych klientów<br />
(operacje nie przeplatają się). Nie istnieje operacja modyfikacji uprzednio<br />
wysłanych wiadomości.<br />
• Usługa <strong>na</strong>zewnicza (jeden piszący, wielu czytających). Obiektem jest pojedynczy<br />
rekord < <strong>na</strong>zwa, adres >. W tym przypadku, występuje tylko<br />
jeden piszący i w zasadzie nie trzeba się zbytnio przejmować spójnością<br />
danych, za wyjątkiem takich zas<strong>to</strong>sowań, które wymagają bezwzględnej<br />
poprawności i świeżości odczytywanych danych.<br />
• Komunikacja <strong>na</strong>tychmias<strong>to</strong>wa (ang. instant messaging) (jeden piszący,<br />
jeden czytający). Obiektem jest komunikacyjny bufor wiadomości. To<br />
zas<strong>to</strong>sowanie jest bezpośrednim odzwierciedleniem problemu producentkonsument.<br />
W tym przypadku, ważne jest, by operacje odczytu zwracały<br />
wiadomości zgodnie z ich kolejnością <strong>na</strong>pływania.<br />
• Obliczenia i koordy<strong>na</strong>cja rozproszo<strong>na</strong> (wielu piszących, wielu czytających).<br />
Obiekt jest elementem obliczeniowym lub semaforem. W tym<br />
przypadku kolejność wykonywanych obliczeń ma zasadnicze z<strong>na</strong>czenie i<br />
ważne jest zagwaran<strong>to</strong>wanie przy<strong>na</strong>jmniej deterministycznego zachowania<br />
usługi, tzn. ta sama sekwencja operacji zleco<strong>na</strong> przez wielu klientów<br />
zwróci taki sam wynik końcowy przy takim samym stanie początkowym<br />
usługi.<br />
Przy<strong>to</strong>czone przykłady rzeczywistych zas<strong>to</strong>sowań usprawiedliwiają realizację<br />
słabszego typu spójności niż spójność sekwencyj<strong>na</strong>, czy <strong>na</strong>wet liniowa. Wydaje<br />
się, że sprostanie warunkom stawianym przez rzeczywiste zas<strong>to</strong>sowania wymaga<br />
zapewnienia spójności przyczynowej (ang. causal consistency) 5 , chociaż w systemie<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> będzie <strong>to</strong> trudne do zapewnienia.<br />
Niezawodne rozgłaszanie. Pro<strong>to</strong>kół uzgadniania wymaga użycia niezawodnego<br />
rozgłasza<strong>na</strong> podczas wysyłania komunikatów do członków grupy. Dlaczego? W<br />
momencie otrzymania zlecenia od klienta replika powin<strong>na</strong> rozesłać zlecenie do<br />
wszystkich pozostałych replik, a <strong>na</strong>stępnie czekać <strong>na</strong> <strong>na</strong>dejście odpowiedzi. Gdy<br />
nie ma gwarancji <strong>na</strong> dostarczenie komunikatu do wszystkich działających replik,<br />
<strong>na</strong>dawca nie ma pewności, czy wszystkie poprawnie działające repliki otrzymały<br />
komunikat. Może okazać się, że podczas rozgłaszania, któraś z replik się odłączyła,<br />
<strong>na</strong>dawca uległ awarii lub zakończył działanie. Niezawodne rozgłaszanie<br />
daje grupie wiedzę <strong>na</strong> temat jej aktualnego składu, czyli repliki mogą decydować<br />
5 Operacje wpływające <strong>na</strong> siebie, powinny zachować porządek wyko<strong>na</strong>nia.
66 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
o tym, które zlecenia zostaną wyko<strong>na</strong>ne a które nie. War<strong>to</strong> zauważyć, że usługa<br />
niezawodnego rozgłaszania nie koniecznie musi gwaran<strong>to</strong>wać w tym przypadku<br />
całkowite uporządkowanie komunikatów (ang. <strong>to</strong>tally ordered multicast), czy<br />
właściwość a<strong>to</strong>mowego rozgłaszania (ang. a<strong>to</strong>mic multicast), która zapewnia, że<br />
wiadomość zostanie dostarczo<strong>na</strong> do wszystkich aktywnych uczestników lub do<br />
nikogo. Zapewnienie niezawodnego rozgłaszania jest konieczne, gdyż wszystkie<br />
poprawnie działające repliki muszą dowiedzieć się o tym, które zlecenia zostały<br />
przez nie pominięte i które powinny wyko<strong>na</strong>ć, by pozostać w synchronizacji z<br />
innymi replikami.<br />
Ogólny opis działania pro<strong>to</strong>kołu. Węzeł po włączeniu się do systemu zostaje<br />
przyłączony do grupy replik, których identyfika<strong>to</strong>ry z<strong>na</strong>jdują się w jego o<strong>to</strong>czeniu.<br />
Jest on zapraszany do istniejącej grupy replik lub tworzy własną grupę.<br />
W pierwszym przypadku, węzeł pobiera stan i zaczy<strong>na</strong> uczestniczyć w wykonywaniu<br />
pro<strong>to</strong>kołu, <strong>na</strong><strong>to</strong>miast w drugiej sytuacji zaprasza szereg replik do swojej<br />
grupy, do momentu gdy osiągnie o<strong>na</strong> oczekiwany rozmiar.<br />
Klient c, może wysłać zlecenie r c s do dowolnej repliki i, przy czym zlecenia<br />
muszą być kolejno ponumerowane przez klienta używając odpowiedniego s.<br />
Repliki działają spełniając zlecenia w rundach r g numerowanych kolejno. Runda<br />
składa się z grupy zleceń odebranych przez repliki od momentu rozpoczęcia poprzedniej<br />
rundy do chwili bieżącej. Rundy są mechanizmem, który wprowadza<br />
pewien s<strong>to</strong>pień synchronizacji w pro<strong>to</strong>kole, podobnie jak ma <strong>to</strong> miejsce BFT w<br />
przypadku s<strong>to</strong>sowania techniki widoków.<br />
Zaletą wyko<strong>na</strong>nia zleceń w rundach w s<strong>to</strong>sunku do wirtualnej synchroniczności<br />
jest rzadka konieczność interwencji, <strong>na</strong>wet gdy któraś z replik przestałaby<br />
odpowiadać. W BFT <strong>na</strong>leży przeprowadzić zmianę widoku zawsze gdy zawodzi<br />
replika głów<strong>na</strong>, a wyz<strong>na</strong>czenie nowej repliki głównej wymaga ponumerowania<br />
replik. Długość rundy może zostać ograniczo<strong>na</strong>, ale wskazane jest, by repliki<br />
dopasowywały długość ok<strong>na</strong> rundy dla wyko<strong>na</strong>nia zleceń w zależności od obciążenia,<br />
podobnie jak w sterowaniu częs<strong>to</strong>ścią zapisu stanu.<br />
Replika otrzymując zlecenie od klienta rozsyła komunikat rozpoczy<strong>na</strong>jący<br />
kolejną rundę vote-request i czeka <strong>na</strong> akceptację od 2f +1 replik uwzględniając<br />
siebie samą, które w odpowiedzi rozgłaszają wek<strong>to</strong>r R j zawierający zlecenia,<br />
które repliki chcą wyko<strong>na</strong>ć w danej rundzie. Każda replika składa wszystkie<br />
wek<strong>to</strong>ry odpowiednio uwzględniając kolejność wyko<strong>na</strong>nia i rozsyła wek<strong>to</strong>r R g<br />
do reszty replik, <strong>na</strong>stępnie czeka <strong>na</strong> 2f +1 takich samych odpowiedzi od różnych<br />
replik uwzględniając siebie samą. Po zebraniu wymaganej liczby komunikatów<br />
replika wybiera pierwsze zlecenie z R g i rozgłasza wiadomość przygo<strong>to</strong>wania<br />
prepare dla tego zlecenia i ponownie czeka <strong>na</strong> odpowiednią liczbę komunikatów.<br />
W <strong>na</strong>stępnej kolejności rozsyła wiadomość pre-commit zawierającą wynik<br />
wyko<strong>na</strong>nia zlecenia. Komunikat commit, zostaje wysłany <strong>na</strong> końcu w celu za-
4.3 Zestaw dostępnych operacji 67<br />
r 1<br />
1<br />
Prepare{r 11 }<br />
Commit{r 11 }<br />
0<br />
1<br />
2<br />
3<br />
r 2<br />
1<br />
R g<br />
{r 1 1 , r 12 }<br />
R g { r 12 }<br />
Vote-request<br />
Pre-commit{r<br />
11 }<br />
Rysunek 4.2: Szkic działania pro<strong>to</strong>kołu dla grupy czterech replik i <strong>na</strong>desłania<br />
zleceń przez dwóch klientów.<br />
twierdzenia wyko<strong>na</strong>nia i musi zostać potwierdzony przez co <strong>na</strong>jmniej f +1<br />
replik. Opisa<strong>na</strong> procedura odpowiada pro<strong>to</strong>kołowi trójfazowego zatwierdzania<br />
[TS01].<br />
W przypadku, gdy replika j wysłała już komunikat vote-response z podanym<br />
wek<strong>to</strong>rem R j , wstawia wszystkie <strong>na</strong>pływające zlecenia do swojej kolejki<br />
i po zakończeniu bieżącej rundy sama może zainicjować nowe wyko<strong>na</strong>nie wysyłając<br />
vote-request. Mechanizm rund wprowadza do pro<strong>to</strong>kołu pewien s<strong>to</strong>pień<br />
synchroniczności, gdyż repliki muszą uzgodnić wyko<strong>na</strong>nie zanim przejdą do<br />
fazy realizacji zleceń. Tutaj <strong>na</strong>leży mieć <strong>na</strong> uwadze twierdzenie wprowadzone<br />
w rozdziale trzecim, które neguje istnienie pro<strong>to</strong>kołu, który byłby całkowicie<br />
asynchroniczny i pozwalał grupie replik dojść do konsensusu w obecności błędów.<br />
4.3 Zestaw dostępnych operacji<br />
Pro<strong>to</strong>kół <strong>bizantyjskie</strong>go uzgadniania pozwala <strong>na</strong> replikację usługi, dlatego moż<strong>na</strong><br />
w oparciu o ten pro<strong>to</strong>kół zrealizować więcej operacji, niż tylko put,get,delete,<br />
które tworzą ogólny interfejs DHT [DZDS03], ale również zaproponowaną w<br />
BFT operację invoke. Nazewnictwo me<strong>to</strong>d pozostanie zgodne z obowiązującym<br />
wsystemiePast [RD01a], który implementuje rozproszoną tablicę z kodowaniem<br />
mieszającym dla obiektów, zbudowany <strong>na</strong> bazie warstwy komunikacyjnej<br />
Pastry. Past nie umożliwia zlecania wyko<strong>na</strong>nia operacji <strong>na</strong> obiektach, jak<br />
również nie jest odporny <strong>na</strong> <strong>bizantyjskie</strong> uszkodzenia. Zaprojek<strong>to</strong>wano system<br />
bardzo podobny do Past o <strong>na</strong>zwie OceanS<strong>to</strong>re opracowany w Berkeley University<br />
of California [KBC + 00], w którego pro<strong>to</strong>typie Pond [REG + 03], zaimple-
68 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
men<strong>to</strong>wano częściowo algorytm SC-ABC. OceanS<strong>to</strong>re zbudowane jest używając<br />
Tapestry - warstwy komunikacyjnej <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, która zdaje się mieć słabszą<br />
wydajność w przekazywaniu komunikatów niż Pastry, jed<strong>na</strong>k gwarantuje większą<br />
niezawodność [LKRG03, ZHS + 03, RD01b]. Projek<strong>to</strong>wany system będzie<br />
realizował <strong>na</strong>stępujące, podstawowe operacje:<br />
insert (id, creds, object) - wprowadza obiekt identyfikowany przez globalnie<br />
unikalny identyfika<strong>to</strong>r id do systemu wraz z uprawnieniami creds 6 .<br />
lookup (id, creds, object*) - zwraca obiekt zidentyfikowany przez id weryfikując<br />
operację przy użyciu uprawnień creds.<br />
invoke (id, creds, operation, params, results*) - wywołuje operację <strong>na</strong><br />
obiekcie identyfikowanym przez id pod warunkiem poprawnej weryfikacji<br />
uprawnień creds. Wynik operacji zwracany jest w zmiennej results.<br />
remove (id, creds) - usuwa obiekt z systemu o identyfika<strong>to</strong>rze id pod<br />
warunkiem poprawnej identyfikacji uprawnień creds.<br />
Podział <strong>na</strong> wyżej wymienione me<strong>to</strong>dy wynika z ich różnorakiej obsługi przez<br />
grupę replikującą. Operacja insert rozpoczy<strong>na</strong> działanie pro<strong>to</strong>kołu <strong>na</strong> rzecz<br />
konkretnego obiektu. Usługa powin<strong>na</strong> stać się dostęp<strong>na</strong>, gdy będzie wiadomo,<br />
że obiekt został umieszczony w przy<strong>na</strong>jmniej 2f +1 replikach. Na rysunku<br />
4.3 pokazano różne możliwe typy zachowania klienta i grupy replik podczas<br />
wprowadzania obiektu. W pierwszym przypadku (a) klient stara się wprowadzić<br />
obiekt do systemu, jed<strong>na</strong>k replika, do której wysłał zlecenie jest nieuczciwa i nie<br />
wypycha kopii obiektu do innych replik; (b) klient rozsyła wiadomość do kilku<br />
replik i czeka <strong>na</strong> odpowiedzi; (c) klient ponownie wysyła komunikat do jednej<br />
z replik i czeka <strong>na</strong> odpowiedź od różnych replik, gdy otrzymają one obiekt.<br />
Gdy obiekt zostanie poprawnie umieszczony w systemie, <strong>to</strong> grupa replik<br />
może zacząć przetwarzanie <strong>na</strong>pływających zleceń. Rozpatrując operację lookup,<br />
łatwo moż<strong>na</strong> zauważyć, że nie modyfikuje o<strong>na</strong> stanu obiektu i może zostać obsłużo<strong>na</strong><br />
<strong>na</strong>wet przez jedną replikę, jed<strong>na</strong>k wymaga również rozpatrzenia kilku<br />
przypadków, gdyż klient może np. wymagać potwierdzenia stanu odebranego<br />
obiektu od większości replik w grupie. Wywołanie invoke jest operacją modyfikującą<br />
stan obiektu, dlatego konieczne jest ustalenie kolejności realizacji zleceń<br />
przez repliki i zatwierdzenie stanu końcowego. Tu niezbędnym jest wprowadzenie<br />
pro<strong>to</strong>kołu uzgadniającego stan. Zakończenie działania pro<strong>to</strong>kołu <strong>na</strong> rzecz<br />
obiektu zachodzi, gdy zostanie odebrane zlecenie remove. Usunięcie obiektu<br />
6 Mechanizm zarządzania i weryfikacji uprawnień został <strong>na</strong>szkicowany w <strong>na</strong>stępnym rozdziale,<br />
który dotyczy projektu systemu Pas<strong>to</strong>r. Na chwilę obecną wystarczy założyć, że uprawnienia<br />
jednoz<strong>na</strong>cznie określają, k<strong>to</strong> i jakie operacje może wyko<strong>na</strong>ć.
4.4 Pro<strong>to</strong>kół zachłanny 69<br />
(a)<br />
(b)<br />
(c)<br />
Rysunek 4.3: Operacja utworzenia kopii obiektu z uwzględnieniem niepoprawnie<br />
działających replik, f = 1. (a) Klient wykonuje jedną kopię, która zostaje<br />
zniszczo<strong>na</strong>. (b) Klient wykonuje 2f +1kopii, jed<strong>na</strong> replika nie odpowiada. (c)<br />
Klient wykonuje jedną kopię, która zostaje wysła<strong>na</strong> do innych replik. Klient<br />
czeka <strong>na</strong> 2f +1odpowiedzi.<br />
musi odbyć się z zachowaniem kolejności <strong>na</strong>pływających operacji. Dalsze wywołania<br />
dotyczące usuniętego obiektu nie mogą być już dalej obsługiwane.<br />
4.4 Pro<strong>to</strong>kół zachłanny<br />
W tym paragrafie zostanie opisany pro<strong>to</strong>kół zachłanny, który realizuje pełną replikację<br />
usługi, odporną <strong>na</strong> błędy <strong>bizantyjskie</strong>. Pro<strong>to</strong>kół gwarantuje poprawność<br />
tak długo, jak tylko liczba replik działających w sposób bizantyjski nie przekracza<br />
f podczas wyko<strong>na</strong>nia.<br />
Inicjacja grupy replik 7 . Zakładamy, że replika może zostać zaproszo<strong>na</strong> do<br />
grupy replikującej lub sama zaprosić inne węzły do grupy tworzonej przez siebie<br />
samą, <strong>na</strong><strong>to</strong>miast nie może sama przyłączyć się do którejś z grup. Skąd bierze<br />
się takie ograniczenie? Po podłączeniu do systemu węzeł może być „bezrobotny”<br />
w tym sensie, że nie <strong>na</strong>leży do żadnej grupy replik i nikt jeszcze nie wysłał do<br />
7 Zarówno w SC-ABC, jak i BFT nie opisano, w jaki sposób grupa replik powin<strong>na</strong> zostać<br />
utworzo<strong>na</strong> zostawiając <strong>to</strong> zagadnienie do rozpatrzenia przez projektantów systemów pod kątem<br />
konkretnego zas<strong>to</strong>sowania. Tworzenie grupy replik określa się częs<strong>to</strong> fazą rozdania (ang. deal<br />
phase).
70 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
(a)<br />
(b)<br />
group-create<br />
failure-detection<br />
group-invite<br />
Rysunek 4.4: Inicjacja grupy replik. (a) Replika tworzy zupełnie nową grupę<br />
używając komunikatu group-create. (b) Replika jest zaproszo<strong>na</strong> do grupy w<br />
miejsce uszkodzonej, rozgłaszany jest komunikat group-invite.<br />
niego zlecenia zapamiętania obiektu. Nie oz<strong>na</strong>cza <strong>to</strong>, że w <strong>to</strong>warzystwie węzła<br />
nie ma grup replikujących, które realizują zlecenia. Widocznie w tym czasie<br />
nowa replika nie jest potrzeb<strong>na</strong>. Pomimo tego, węzeł, który dopiero co włączył<br />
się do systemu, powinien spróbować utworzyć własną grupę replik, gdyż za<br />
chwilę może otrzymać zlecenie zapamiętania obiektu. Nie <strong>na</strong>leży zwlekać, gdyż<br />
tworzenie grupy w chwili otrzymania pierwszego zlecenia z<strong>na</strong>cznie obniżałoby<br />
wydajność, ponieważ utworzenie nowej grupy jest bardzo pracochłonne. Gdybyśmy<br />
zezwolili <strong>na</strong> swobodne przyłączanie do grupy replik możliwym stałoby<br />
się, że kilka replik sparaliżowałaby pracę przyłączając się i odłączając dowolnie<br />
częs<strong>to</strong>.<br />
Rozpatrzę sytuację, gdy nowa grupa replik tworzo<strong>na</strong> jest przez węzeł:<br />
1. Do z<strong>na</strong>nych węzłów rozsyłany jest komunikat propozycji utworzenia grupy<br />
< group-create, i id , g id , G> σi . Identyfika<strong>to</strong>r i id jest identyfika<strong>to</strong>rem węzła<br />
proponującego utworzenie grupy, g id jest wygenerowanym identyfika<strong>to</strong>rem<br />
grupy, <strong>na</strong><strong>to</strong>miast G <strong>to</strong> wek<strong>to</strong>r identyfika<strong>to</strong>rów węzłów, do których został<br />
<strong>na</strong>dany komunikat włączając też twórcę grupy.<br />
2. W odpowiedzi węzły rozgłaszają komunikat do wszystkich węzłów w G,<br />
który precyzuje, czy chcą przyłączyć się do grupy, czy też nie 8 < groupjoin,<br />
j id , v> σj , gdzie v = {0, 1} w zależności od odpowiedzi.<br />
3. Każdy z węzłów zbiera odpowiedzi i składa je w wek<strong>to</strong>r J otakimsamym<br />
uporządkowaniu jak G, gdzie J(j) =1, gdy uczestnik o identyfika<strong>to</strong>rze<br />
8 Nie ma przymusu przy włączaniu się do grupy.
4.4 Pro<strong>to</strong>kół zachłanny 71<br />
G(j) wyraził chęć przyłączenia się do grupy J(j) =0, w przypadku odmowy,<br />
oraz J(j) =−1, gdy węzeł odpowiedzi nie otrzymał. Rozpoczęcie<br />
składania wek<strong>to</strong>ra J powinno <strong>na</strong>stąpić w momencie otrzymania:<br />
⌊ ⌋ 2n +1<br />
k> ,<br />
3<br />
gdzie n oz<strong>na</strong>cza liczbę węzłów w G. Wek<strong>to</strong>rJ rozgłaszany jest do wszystkich<br />
węzłów w G, < group-prelist, J> σj . War<strong>to</strong>ść k w tym przypadku<br />
oz<strong>na</strong>cza większość 2 węzłów w G, które odpowiedziały. Jeżeli dalej<br />
3<br />
wszystkie węzły włączą się do grupy <strong>to</strong> zakładamy, że jed<strong>na</strong> trzecia z<br />
nich może <strong>na</strong>dal być nieuczciwa. Wniosek jest taki, że węzeł chcąc osiągnąć<br />
grupę, w której f węzłów może być podejrzanych o nieuczciwość,<br />
musi rozesłać propozycję przyłączenia się do grupy, do co <strong>na</strong>jmniej<br />
n ≥ 9 2 f +1<br />
Ostatnia zależność wynika z warunku <strong>na</strong> k oraz warunku <strong>na</strong> liczbę replik<br />
jaka musi istnieć w grupie, by uzgodnienie było możliwe n ≥ 3f +1.<br />
Dla przykładu, gdy f =1,<strong>to</strong>n musi być większe bądź równe 6. Pojawia<br />
się pytanie, co zrobić gdy nie uda się spełnić tego warunku. Pozostaje<br />
stworzyć grupę z tylu replik, z ilu jest <strong>to</strong> możliwe.<br />
4. Kolejną fazą jest wymia<strong>na</strong> kluczy szyfrujących. Każda z replik powin<strong>na</strong><br />
posiadać klucze sesyjne współdzielone z innymi replikami <strong>na</strong>leżącymi do<br />
grupy, w celu weryfikacji i szyfrowania wysyłanych komunikatów. Węzeł<br />
j wybiera kolejno węzeł G(l), l =(j + i) mod n, i ∈{1,...,n},<br />
dla którego J(k) =1i rozpoczy<strong>na</strong> z nim proces uzgadniania klucza, np.<br />
używając algorytmu Diffie-Hellman’a [MVO96]. Gdyby wybrany węzeł<br />
nie odpowiedział lub gdy klucz został już ustalony, wybiera się kolejny<br />
węzeł. Przejście po elementach G(l) powinno odbyć się więcej niż jeden<br />
raz, by ponowić próbę ustalenia klucza dla tych węzłów, z którymi<br />
nie udało się tego przeprowadzić w uprzedniej iteracji. Technika przechodzenia<br />
po wek<strong>to</strong>rze G począwszy od kolejnej repliki za inicjującym<br />
negocjację, jest bardzo prostą techniką równoważenia obciążenia podobną<br />
do algorytmu karuzelowego (ang. round robin). Po określonej liczbie prób<br />
węzeł dysponuje kluczami dla grupy replik. Zakończenie tej fazy powinno<br />
być rozgłoszone < group-postlist, Ĵ > σj , gdzie Ĵ jest wek<strong>to</strong>rem o tych<br />
samych elementach co J z <strong>na</strong>niesioną informacją o tym, z kim udało się<br />
wynegocjować klucz.<br />
5. Odebranie przy<strong>na</strong>jmniej k wiadomości group-postlist, w których przy<strong>na</strong>jmniej<br />
k elementów jest równych 1 kończy fazę tworzenia grupy.
72 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
Podczas wyko<strong>na</strong>nia algorytmu może okazać się, że jakaś z replik przestała<br />
działać, tak jak zostało <strong>to</strong> przedstawione <strong>na</strong> rysunku 4.2. Gdy awaria, którejś z<br />
replik zostanie wykryta oraz liczba replik jest <strong>na</strong> granicy gwarancji poprawnego<br />
działania pro<strong>to</strong>kołu, <strong>to</strong> powinno <strong>na</strong>stąpić uruchomienie procedury zaproszenia<br />
nowejreplikidogrupy 9 :<br />
1. Replika i rozgłasza komunikat < group-invite, g id , G, r g , j > σi do węzła<br />
j z<strong>na</strong>jdującego się w sąsiedztwie grupy oraz do reszty replik w G. G jest<br />
wek<strong>to</strong>rem wszystkich identyfika<strong>to</strong>rów replik, które przy<strong>na</strong>leżą do grupy<br />
oz<strong>na</strong>czonej g id .<br />
2. Węzeł zaproszony j odpowiada komunikatem < group-join, j, G> σj do<br />
wszystkich węzłów w G. Następnie j wykonuje procedurę negocjacji klucza<br />
z węzłami w G opisaną uprzednio i buduje wek<strong>to</strong>r J, który rozgłasza<br />
po zakończeniu procedury < group-prelist, J> σj , czeka <strong>na</strong> odpowiedzi od<br />
poszczególnych uczestników i buduje wek<strong>to</strong>r Ĵ, który <strong>na</strong>stępnie rozgłasza.<br />
3. Kolejny krok prowadzi do pobrania i uzgodnienia aktualnego stanu usługi.<br />
Replika wysyła komunikat < state-request, j, r g > σj , gdzie r g jest numerem<br />
rundy, dla której replika z<strong>na</strong> ostatni stabilny stan 10 . W przypadku, gdy<br />
replika nie z<strong>na</strong> żadnego stabilnego stanu wysyła r g =0. Odpowiadając<br />
repliki wysyłają < state-response, i, r g , H(s) > σj . Replika po potrzymaniu<br />
2f +1 takich samych odpowiedzi od różnych replik przystępuje do<br />
pobrania stanu. Replika może wyko<strong>na</strong>ć tę operację równolegle pobierając<br />
tylko pewne części stanu od różnych replik wysyłając komunikat < statefetch,<br />
j, H(s), p> σj , p oz<strong>na</strong>cza numer fragmentu. Pobranie może być<br />
zrealizowane podobnie, jak w pro<strong>to</strong>kole BitTorrent (opisany w rozdziale<br />
pierwszym) odbywa się pobieranie zasobu, gdyby stan usługi okazał się<br />
być bardzo duży (pobranie <strong>na</strong>wet 1MB <strong>na</strong> chwilę pisania tej pracy, może<br />
okazać się problematyczne).<br />
4. Oczywiście może okazać się, że stan, którym dysponuje replika tuż po<br />
transferze zdążył się już zestarzeć, dlatego musi on zostać jeszcze odświeżony.<br />
Po zakończeniu pobierania stanu replika rozgłasza < state-update,<br />
j, r g , H(s) > σj . W odpowiedzi repliki wysyłają komunikat < state-renew,<br />
i, r ′ g , R(s) > σ i<br />
, gdzie R(s) jest listą list wszystkich zleceń, które <strong>na</strong>leży<br />
wyko<strong>na</strong>ć aby przejść ze stanu s do stanu s ′ i do obowiązującej rundy r ′ g,<br />
spójnej z innymi replikami. Lista R(s) ma r ′ g − r g list, w których z<strong>na</strong>jdują<br />
się zlecenia dla każdej wyko<strong>na</strong>nej rundy.<br />
9 W <strong>na</strong>stępnym rozdziale zostanie pokazane, w jaki sposób konstruować rzeczywistą grupę,<br />
by zapewnić maksymalny s<strong>to</strong>pień odporności <strong>na</strong> uszkodzenia.<br />
10 Ten parametr będzie używany w momencie powtórnego przyłączania repliki.
4.4 Pro<strong>to</strong>kół zachłanny 73<br />
Uzgadnianie wielowar<strong>to</strong>ściowe. Zanim repliki przystąpią do wyko<strong>na</strong>nia zlecenia<br />
muszą tą czynność potwierdzić za pomocą wielowar<strong>to</strong>ściowego uzgadniania<br />
opisanego w poprzednim rozdziale. Pro<strong>to</strong>kół realizujący wyko<strong>na</strong>nie zleceń <strong>na</strong>dsyłanych<br />
do grupy przez klientów jest wykonywany w <strong>na</strong>stępujących krokach:<br />
1. Gdy replika i otrzyma zlecenie r c s wysyła komunikat < vote-request, r g ,<br />
R i = r c s > σi do wszystkich replik, gdzie r g , <strong>to</strong> aktualny numer rundy,<br />
a R i , <strong>to</strong> wek<strong>to</strong>r zleceń, w tym przypadku zakładamy, że replika nie posiadała<br />
żadnych zleceń w kolejce Q i . Gdyby okazało się, że w kolejce<br />
są zlecenia, <strong>to</strong> powinny zostać umieszczone <strong>na</strong> początku wek<strong>to</strong>ra R i ,tak<br />
by zlecenia były ułożone z rosnącym porządkiem sekwencji s rozpatrując<br />
poszczególnych klientów (np. R i = {r 1 1 ,r 1 2 ,r 3 2 ,,...}). War<strong>to</strong> zauważyć,<br />
że sposób uporządkowania elementów w R i ustawia zlecenia <strong>na</strong>dane przez<br />
tych samych klientów w jednej grupie. Takie postępowanie zapewnia brak<br />
wystąpienia konfliktów typu zapis-zapis w obrębie jednej rundy.<br />
2. Odebranie komunikatu < vote-request, r g , R j = r s c > σj <strong>na</strong>kłada obowiązek<br />
rozesłania odpowiedzi przez replikę, używając komunikatu < voteresponse,<br />
r g , R i > σi . Jeżeli r g okazałoby się nieprawidłowe, <strong>to</strong> replika<br />
powin<strong>na</strong> odpowiedzieć komunikatem z poprawnym r g . Komunikat voteresponse<br />
powinien zostać <strong>na</strong>dany wtedy i tylko wtedy, gdy replika wcześniej<br />
nie wysłała własnego komunikatu vote-request dla rundy o numerze<br />
r g . Replika otrzymawszy f +1 wiadomości z r g , różnym od własnego, ale<br />
takim samym z<strong>na</strong>czniku, powin<strong>na</strong> wprowadzić korektę i rozesłać jeszcze<br />
raz vote-response z poprawnym r g .<br />
3. Zgromadzenie przez i-tą replikę 2f +1 odpowiedzi vote-response uwzględniając<br />
siebie samą i/lub vote-request rozpoczy<strong>na</strong> fazę uzgadniania. Wek<strong>to</strong>ry<br />
R j składane są przez replikę w jeden wek<strong>to</strong>r R g zachowując porządek<br />
taki sam jak w R i , który <strong>na</strong>stępnie jest rozgłoszony < request-ready, r g ,<br />
R g > σi .Zebranief +1 takich samych komunikatów request-ready, może<br />
rozpocząć fazę przetwarzania zleceń.<br />
4. Pro<strong>to</strong>kół, który realizuje wyko<strong>na</strong>nie każdego zlecenia składa się z trójfazowego<br />
uzgadniania każdego wyko<strong>na</strong>nia:<br />
• Pierwszym komunikatem rozsyłanym przez replikę, jest < prepare,<br />
r g , H(R g (k)) > σi dla k-tego zlecenia w wek<strong>to</strong>rze R g .<br />
• Po odebraniu 2f +1 komunikatów prepare dla zlecenia R g (k), replika<br />
wykonuje żądanie i wysyła komunikat < pre-commit, r g , V g (k)<br />
> σi , który po odebraniu od 2f +1 powinien zostać potwierdzony komunikatem<br />
< commit, r g , H(V g (k)) > σi , co ostatecznie zatwierdza<br />
wyko<strong>na</strong>nie operacji R g (k).
74 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
• Potwierdzenie zebrane od f +1 replik wystarcza, by zatwierdzić<br />
zlecenie i wysłać odpowiedź klien<strong>to</strong>wi 11 , jed<strong>na</strong>k dopiero 2f +1potwierdzeń<br />
jest dowodem tego, że stan replik jest spójny i może zostać<br />
zatwierdzony.<br />
• Przetwarzanie odbywa się tak długo, jak w wek<strong>to</strong>rze R g pozostają<br />
zlecenia do wyko<strong>na</strong>nia.<br />
Pro<strong>to</strong>kół opisany w tym paragrafie będzie dalej oz<strong>na</strong>czany symbolem BF2.<br />
Wzajemne wykluczanie. Ponieważ wszystkie repliki w grupie wykonują zlecenia<br />
uporządkowane według kolejności w R g , zatem istnieje potencjal<strong>na</strong> możliwość<br />
łatwego poszerzenia algorytmu o wzajemne wykluczanie. W tym celu<br />
klient c wysyła <strong>na</strong> początku specjalne zlecenie zajęcia usługi (ang. lock) . Repliki<br />
<strong>na</strong>potykając zlecenie lock wwek<strong>to</strong>rzeR g sprawdzają czy wśród reszty<br />
zleceń od tego samego klienta, który zamówił obiekt jest zlecenie zwolnienia<br />
(ang. release). Jeżeli zlecenie release z<strong>na</strong>jduje się w R g <strong>to</strong> repliki nie robią nic.<br />
Jeżeli <strong>na</strong><strong>to</strong>miast zlecenie <strong>to</strong> nie występuje, <strong>to</strong> resztę zleceń ustawiają w kolejce<br />
typu FIFO oz<strong>na</strong>czonej np. Q Rg , wykonują zlecenia klienta c i przechodzą do<br />
<strong>na</strong>stępnej rundy. Zlecenia zebrane w kolejnej rundzie są ustawiane <strong>na</strong> koniec kolejki<br />
Q Rg jeżeli pochodzą od innych klientów, aż do momentu <strong>na</strong>potkania relase<br />
od klienta c. Wtedy w kolejnej rundzie wykonuje się zlecenia zebrane w Q Rg .<br />
Należy zagwaran<strong>to</strong>wać, by podczas wyko<strong>na</strong>nia nie wystąpiło przywłaszczenie<br />
usługi, tzn. że tylko jeden klient ciągle będzie zajmował obiekt. W tym celu<br />
moż<strong>na</strong> użyć <strong>na</strong>stępującego algorytmu:<br />
Załóżmy, że z<strong>na</strong>my identyfika<strong>to</strong>ry wszystkich klientów 12 . Z każdym identyfika<strong>to</strong>rem<br />
kojarzymy licznik początkowo równy zero. Gdy klient otrzyma wyłączny<br />
dostęp do obiektu, <strong>to</strong> jego licznik zostaje pomniejszony o jeden, a liczniki<br />
wszystkich innych klientów zostają powiększone o jeden. War<strong>to</strong>ść wskazania<br />
licznika nie może być mniejsza od zera, czyli gdy licznik osiągnie zero <strong>to</strong> odjęcie<br />
od tej war<strong>to</strong>ści jedności nie zmienia wskazania. W momencie pojawienia się<br />
kolejnego zlecenia zamówienia obiektu dla kilku różnych klientów, sprawdzany<br />
jest stan licznika i ten klient dostanie wyłączny dostęp, dla którego licznik ma<br />
większą war<strong>to</strong>ść. Procedura po przyz<strong>na</strong>niu wyłącznego dostępu odejmuje jeden<br />
od licznika klienta, <strong>na</strong><strong>to</strong>miast pozostałym dodaje jeden. Algorytm jest odporny<br />
<strong>na</strong> zagładzanie, jednocześnie gwarantuje, że jeżeli tylko jeden z klientów będzie<br />
nieustannie żądał dostępu, <strong>to</strong> będzie on mu przyz<strong>na</strong>wany. Ilustrację działania<br />
11 Zalecane jest użycie schematu przyros<strong>to</strong>wych podpisów cyfrowych, który pozwala zapamiętać<br />
szereg podpisów stanu, jako jeden spójny podpis, który moż<strong>na</strong> <strong>na</strong>stępnie łatwo weryfikować.<br />
W innym przypadku odpowiedź <strong>na</strong> zlecenie r s c jest wysyła<strong>na</strong> przez wszystkie repliki.<br />
12 Takie założenie jest bardzo mocne, ale jest wprowadzone tylko dlatego, żeby łatwiej wyjaśnić<br />
sposób działania algorytmu. Warunek ten zostanie później osłabiony.
4.4 Pro<strong>to</strong>kół zachłanny 75<br />
(a)<br />
(b)<br />
K1<br />
K2<br />
K3<br />
K4<br />
K1<br />
K2<br />
K3<br />
K4<br />
lock<br />
lock<br />
lock<br />
Q: {K1}<br />
K1<br />
1<br />
K2<br />
0<br />
K3<br />
1<br />
K4<br />
1<br />
K1<br />
2<br />
K2<br />
1<br />
K3<br />
0<br />
K4<br />
2<br />
Rysunek 4.5: (a) Obiekt jest zamawiany przez klienta K1, liczniki pozostałych<br />
klientów są powiększane. (b) Obiekt chce zająć klient K1 oraz K2. Licznik<br />
K2 był uprzednio większy od K1 dlatego jemu pierwszemu przydzielany jest<br />
wyłączny dostęp. K1 czeka w kolejce.<br />
algorytmu gwarantującego sprawiedliwy dostęp pokazano <strong>na</strong> rysunku 4.5. W<br />
praktycznej realizacji <strong>na</strong>leży pamiętać liczniki tylko dla klientów wysyłających<br />
zlecenia lock. Dla reszty klientów war<strong>to</strong>ść licznika, jest sumą wszystkich zrealizowanych<br />
leceń, co osłabia początkowe założenie. Sytuacja, w której klient,<br />
blokujący obiekt, ulega awarii wymaga cofnięcia operacji przez niego wyko<strong>na</strong>nych.<br />
Rozpoz<strong>na</strong>nie, czy klient działa prawidłowo moż<strong>na</strong> zrealizować poprzez<br />
mechanizm czasowej dzierżawy (ang. lease) [TS01]. Dzierżawa polega <strong>na</strong> tym,<br />
że klient co jakiś czas wysyła komunikat odnowienia blokowania. Jeżeli zdarzyłoby<br />
się, że zlecenie odnowienia nie przyjdzie w określonym specjalnie interwale<br />
czasu, <strong>to</strong> obiekt zostaje zwolniony.<br />
Przyłączanie i odłączanie repliki. Częs<strong>to</strong> zdarza się, że węzeł odłączy się<br />
jedynie <strong>na</strong> chwilę, a po upływie niewielkiego czasu powraca do grupy. Oczywiście<br />
dobrze, by przed rozłączeniem replika oz<strong>na</strong>jmiła chęć swojego opuszczenia<br />
grupy np. rozsyłając komunikat < group-leave, i> σi . Ponowne przyłączenie,<br />
może odbyć się po wyko<strong>na</strong>niu <strong>na</strong>stępujących kroków:<br />
1. Replika chcąc przyłączyć się ponownie do grupy, rozgłasza komunikat <<br />
group-rejoin-request, i, r g > σi , podobnie jak miało <strong>to</strong> miejsce w przypadku<br />
przyłączania nowej repliki. Replika nie posiada informacji o tym, czy stan<br />
grupy zdążył się zmienić od jej ostatniego wyłączenia, dlatego musi tę<br />
wiedzę uzyskać od innych replik.<br />
2. Uprzednio wysłany komunikat może nie dotrzeć do części członków, o<br />
których wiedziała replika j, gdyż stan grupy mógł się zmienić. Repliki
76 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
(a)<br />
(b)<br />
group-leave<br />
group-rejoin<br />
rejoin<br />
Rysunek 4.6: Odłączanie i przyłączanie repliki do grupy. (a) Replika oz<strong>na</strong>jmia<br />
swoje odłączenie rozsyłając komunikat group-leave. (b) Ponownie włączając się<br />
do grupy replika <strong>na</strong>jpierw rozgłasza group-rejoin. Konieczne jest ustalenie przez<br />
ponownie przyłączającą się replikę, aktualnego składu grupy.<br />
odpowiadają komunikatem < group-rejoin-response, j, r ′ g, H(s), G j > σj ,<br />
gdzie G j jest wek<strong>to</strong>rem węzłów z<strong>na</strong>nych przez replikę j.<br />
3. Replika powiadamia węzły w G, których nie z<strong>na</strong>, że ponownie przyłącza<br />
się do grupy. Z niez<strong>na</strong>nymi jej uczestnikami musi wynegocjować klucze<br />
oraz zaktualizować stan podobnie, jak nowo przyłączająca się replika. Węzeł<br />
i wykonuje opisaną procedurę negocjacji klucza z węzłami w G, których<br />
nie z<strong>na</strong> budując wek<strong>to</strong>r, który rozgłasza po zakończeniu procedury<br />
< group-rejoin-prelist, J > σj , czeka <strong>na</strong> odpowiedzi od poszczególnych<br />
uczestników i buduje wek<strong>to</strong>r Ĵ, który ponownie rozgłasza < group-rejoinpostlist,<br />
Ĵ> σj .<br />
4. Zakończenie procedury odbywa się po tym, jak replika doprowadzi swój<br />
stan do zgodnego z innymi replikami. W tym celu wysłany jest przez<br />
replikę komunikat state-update, co zostało opisane w punkcie dotyczącym<br />
inicjacji grupy replik i zapraszania repliki do grupy.<br />
Odłączenie, uszkodzenie klienta. Koniecznym wydaje się rozpatrzenie przypadku,<br />
gdy klient zostałby uszkodzony, lub odłączył się od systemu. Nie mamy<br />
gwarancji, że po ponownym uruchomieniu, będzie on pamiętał ostatnią sekwencję<br />
wysłanego zlecenia. Możliwe są trzy podejścia do tego problemu:<br />
• Pierwsze zlecenie wysłane przez klienta po uszkodzeniu powinno być specjalnym<br />
komunikatem typu, client-anounce, który zapoz<strong>na</strong> repliki z klientem<br />
i zawiadomi, że <strong>na</strong>stąpiło jego ponowne uruchomienie.<br />
• Identyfika<strong>to</strong>r klienta c zmienia się po awarii.
4.4 Pro<strong>to</strong>kół zachłanny 77<br />
Zdarzenie Przyczy<strong>na</strong> Reakcja<br />
A1 Usługa może działać niedeterministycznie,<br />
gdy takie zachowanie występuje<br />
dla grupy z dużą liczbą replik.<br />
A2 Wystąpiła awaria w warstwie komunikacyjnej<br />
lub komunikaty zostały<br />
wstrzymane.<br />
A3 W grupie replik może z<strong>na</strong>jdować<br />
się część węzłów niepoprawnie<br />
działających, których działanie<br />
wynika z błędnej implementacji.<br />
B1 Wystąpiło masowe przyłączanie i<br />
odłączanie węzłów.<br />
B2 Wystąpiła awaria w warstwie komunikacyjnej<br />
lub komunikaty zostały<br />
wstrzymane.<br />
B3 Część z węzłów nie ma połączeń z<br />
resztą grupy.<br />
C1<br />
C2<br />
Stan replik nie jest zsynchronizowany.<br />
Taka sytuacja może być <strong>na</strong>stępstwem<br />
A1, lub tym, że pro<strong>to</strong>kół<br />
zawiódł.<br />
Uszkodzenia w komunikacji lub za<br />
mała liczba członków grupy.<br />
Rezyg<strong>na</strong>cja z wyko<strong>na</strong>nia usługi lub<br />
losowy wybór spośród replik nowego<br />
globalnego stanu.<br />
Ponowienie wysłania ostatniego<br />
komunikatu.<br />
Brak propozycji.<br />
Starać się wynegocjować, jak <strong>na</strong>jwiększą<br />
możliwą grupę.<br />
Ponowienie wysłania ostatniego<br />
komunikatu. Wstrzymanie negocjacji.<br />
Należy ustalić węzły, które mają<br />
<strong>na</strong>jlepszy obraz grupy i próbować<br />
przez nie <strong>na</strong>wiązać komunikację.<br />
Wstrzymanie transferu stanu i ponowienie<br />
próby po jakimś czasie.<br />
Ponowienie próby transferu po jakimś<br />
czasie lub zaniechanie.<br />
C3 Prawdopodobnie wystąpił A3. Ponowienie próby transferu po jakimś<br />
czasie lub zaniechanie.<br />
Tablica 4.1: Zestawienie incydentów, do których może dojść podczas wyko<strong>na</strong>nia<br />
pro<strong>to</strong>kołu.<br />
• Nie przejmować się i pracować dalej, jakby nic się nie stało.<br />
Pierwsze i drugie podejście wyklucza zaistnienie problemów z nieprawidłowym<br />
uporządkowaniem zleceń, ale wymaga dodatkowego <strong>na</strong>kładu pracy. Ostatnie<br />
podejście, chociaż trochę kontrowersyjne, może okazać się wystarczające w<br />
przypadku poprawnie działających aplikacji klienckich. Nie <strong>na</strong>leży obawiać się<br />
klientów, którzy chcieliby zdestabilizować pracę grupy, gdyż jakiekolwiek nieciągłości<br />
w numeracji sekwencji powinny prowadzić do zatrzymania wykonywania<br />
zleceń dla danego klienta, a <strong>to</strong>, że np. niektóre zlecenia będą posiadały ten sam<br />
numer sekwencji spowoduje tylko, że klient może otrzymać odpowiedzi, które<br />
niekoniecznie będą odzwierciedlały spodziewane działanie usługi. Taka sytuacja<br />
może doprowadzić do powstania błędów przetwarzania, zatem dużo zależy od<br />
poprawnej implementacji.
78 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
Incydenty. Incydentem <strong>na</strong>zywamy sytuację, gdy podczas wykonywania pro<strong>to</strong>kołu<br />
warunek <strong>na</strong> liczbę takich samych odpowiedzi od różnych <strong>na</strong>dawców nie jest<br />
spełniony.<br />
Tak, jak w prawdziwym świecie reakcja <strong>na</strong> incydent powin<strong>na</strong> być przemyśla<strong>na</strong>.<br />
Najpierw <strong>na</strong>leży przea<strong>na</strong>lizować dostępne informacje, <strong>na</strong>stępnie wyciągnąć<br />
z nich wnioski i podjąć odpowiednią decyzję. Działanie trzeba podjąć<br />
<strong>na</strong>tychmiast, gdyż częs<strong>to</strong> jedynie szybka reakcja potrafi przywrócić właściwy<br />
stan. Incydenty w opisanym pro<strong>to</strong>kole mogą pojawiać się w <strong>na</strong>stępujących przypadkach:<br />
A. Uzgadnianie stanu po wyko<strong>na</strong>niu zlecenia.<br />
B. Uzgadnianie składu grupy replik.<br />
C. Transfer stanu między replikami.<br />
Dodatkowo każdy incydent może mieć <strong>na</strong>stępujący charakter:<br />
1. Przypadkowy. Nadesłane odpowiedzi mają losowe war<strong>to</strong>ści.<br />
2. Odmowy. Nadesłanych odpowiedzi jest za mało, by zagwaran<strong>to</strong>wać<br />
poprawne działanie.<br />
3. „Koordynowanego buntu”. Nadesłane odpowiedzi dają się podzielić <strong>na</strong><br />
kilka grup. Niestety żad<strong>na</strong> nie tworzy wymaganej większości.<br />
Iloczyn kartezjański charakteru incydentu i przypadku występowania prowadzi<br />
do pełnej listy incydentów (patrz tablica 4.1) oraz możliwych reakcji.<br />
4.5 Zatwierdzanie stanu<br />
Opisywa<strong>na</strong> technika transferu stanu wymaga istnienia mechanizmu, który zatwierdzałby<br />
stan usługi, jako stabilny. De fac<strong>to</strong> moż<strong>na</strong> w tym miejscu posłużyć<br />
się techniką zatwierdzania stanu (ang. checkpointing) opisaną w poprzednim<br />
rozdziale, użytą w algorytmie BFT.<br />
Pozostaje do rozpatrzenia, czy rzeczywiście zatwierdzanie stanu musi odbywać<br />
się w sposób bezpośrednio koordynowany oraz czy wymaga zebrania „dowodu<br />
stabilności”. Poprzez bezpośrednią koordy<strong>na</strong>cję <strong>na</strong>leży rozumieć technikę,<br />
która wymaga komunikacji grupowej oraz doprowadzi do wspólnego zatwierdzenia<br />
stanu.<br />
Na rysunku 4.7 pokazano, że dowolny moment zatwierdzenia stanu przez<br />
replikę może prowadzić do jej awarii. Dlaczego? Przecież moż<strong>na</strong> transferować<br />
stan od repliki o numerze trzecim, oraz wszystkie zlecenia, tak, że replika
4.5 Zatwierdzanie stanu 79<br />
0<br />
1<br />
2<br />
3<br />
s 3<br />
s 0<br />
s 1<br />
s 2<br />
{s 0 , s 1 ,s 2 ,s 3 }<br />
Rysunek 4.7: Przebieg z lokalnym zapamiętywaniem stanu przez repliki. Po<br />
ponownym podłączeniu czwarta replika nie jest w stanie odzyskać sprawności.<br />
czwarta będzie odświeżo<strong>na</strong>? Niestety nie moż<strong>na</strong> tak postąpić z powodu braku<br />
zaufania, do którejkolwiek z replik. Oczywiście replika, która uległa awarii<br />
ufa samej sobie, dlatego stan s 3 , którym replika dysponuje jest akcep<strong>to</strong>walny<br />
przez nią samą, jed<strong>na</strong>kże <strong>na</strong>wet po odczytaniu stanu s 3 <strong>na</strong>dal będą niedostępne<br />
zlecenia, które przeprowadzą s 3 do aktualnie obowiązującego stanu. Brakujące<br />
zlecenia mogłyby być pobrane od repliki o numerze zero, jed<strong>na</strong>k sytuacja przedstawio<strong>na</strong><br />
<strong>na</strong> rys. 4.7 jest tylko specyficznym przypadkiem. Mogłoby się zdarzyć,<br />
że ostatni zatwierdzony stan przez replikę odbył się w czasie, gdy replika trzecia<br />
uległa awarii, wtedy zleceń nie udałoby się odzyskać.<br />
W pro<strong>to</strong>kole BFT pokazano, że zatwierdzanie stanu musi odbywać się w<br />
sposób koordynowany. Częs<strong>to</strong>ść zatwierdzania powin<strong>na</strong> być dopasowa<strong>na</strong> do<br />
obciążenia. Zatwierdzenie stanu powinno odbywać się tak częs<strong>to</strong>, jak jest <strong>to</strong><br />
możliwe, jed<strong>na</strong>k, nie <strong>na</strong> tyle częs<strong>to</strong>, by w z<strong>na</strong>cznym s<strong>to</strong>pniu obciążać usługę.<br />
Z drugiej strony zatwierdzenie stanu nie może być za rzadkie, gdyż może <strong>to</strong><br />
doprowadzić do załamania usługi w przypadku awarii. Generalnie problem częs<strong>to</strong>ści<br />
wykonywania migawek <strong>na</strong>leżałoby rozwiązać budując odpowiednie prawo<br />
sterowania, co mogłoby stanowić osobne opracowanie i w tej pracy zostało tylko<br />
zasyg<strong>na</strong>lizowane.<br />
Sterowanie czasem zapisu migawki. Przez pojęcie stanu usługi będziemy rozumieli<br />
stabilną migawkę 13 obiektu oraz wszystkie zlecenia, które jeszcze nie<br />
zostały wyko<strong>na</strong>ne. Nie uwzględniamy komunikatów, które z<strong>na</strong>jdują się w ka<strong>na</strong>łach<br />
komunikacyjnych i nie zostały potwierdzone przez większość replik.<br />
Możliwe są dwa podejścia wynikające z założenia, jak uwzględniamy czas<br />
potrzebny do wyko<strong>na</strong>nia zapisu stanu:<br />
1. Czas odzyskania stanu usługi jest mały w porów<strong>na</strong>niu do czasu wyko<strong>na</strong>nia<br />
zleceń - migawki war<strong>to</strong> wykonywać, jak <strong>na</strong>jczęściej.<br />
13 Czyli obiekt nie będący podczas tranzycji stanu wewnętrznego (wyko<strong>na</strong>nia).
80 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
35<br />
12<br />
11<br />
30<br />
10<br />
25<br />
20<br />
9<br />
8<br />
7<br />
6<br />
15<br />
0 100 200 300 400 500 600 700 800 900 1000 1100<br />
5<br />
0 100 200 300 400 500 600 700 800 900 1000 1100<br />
Rysunek 4.8: Sterowanie częs<strong>to</strong>ścią zapisu stanu (prawa stro<strong>na</strong>) dla zmieniającego<br />
się czasu wyko<strong>na</strong>nia usługi (lewa stro<strong>na</strong>) (L max = 100, t=20, δ =0.5).<br />
2. Czas wyko<strong>na</strong>nia zleceń jest mały w porów<strong>na</strong>niu do czasu odzyskania usługi<br />
stanu - migawki <strong>na</strong>leży wykonywać w momencie zapełnienia dziennika,<br />
<strong>na</strong>jrzadziej jak <strong>to</strong> jest możliwe.<br />
Przea<strong>na</strong>lizuję sytuację drugą, gdyż dla pierwszego przypadku opłaca się archiwizować<br />
dane dowolnie częs<strong>to</strong>. T będzie oz<strong>na</strong>czało ostatni okres wyko<strong>na</strong>nia<br />
migawki. Niech t T oz<strong>na</strong>cza średni czas wyko<strong>na</strong>nia rundy od ostatniej migawki,<br />
<strong>na</strong><strong>to</strong>miast l T średnią długość dziennika, który powstaje podczas wyko<strong>na</strong>nia rund<br />
od ostatniej migawki. Odpowiednio definiujemy war<strong>to</strong>ści średnie za okres równy<br />
2T - t 2T , l 2T . Nowy wyz<strong>na</strong>czony okres między zapisami migawki oz<strong>na</strong>czymy<br />
T ,<strong>na</strong><strong>to</strong>miastT max = Lmax− l T<br />
l T<br />
, maksymalny okres wynikający z rozmiaru dziennika.<br />
Wyz<strong>na</strong>czenie okresu kolejnej migawki T ′ będzie przebiegało z wykorzystaniem<br />
prostej formuły:<br />
T ′ = δ<br />
(<br />
tT<br />
t 2T<br />
l T<br />
l 2T<br />
) −1<br />
T max<br />
Początkowa war<strong>to</strong>ści T ′ , dla której rozpoczy<strong>na</strong> się działanie, powin<strong>na</strong> być<br />
taka, by nie przekroczyć dozwolonej długości dziennika. Parametr δ ∈〈0, 1〉<br />
jest odpowiedzialny za dodatkową regulację war<strong>to</strong>ści T i powinien być wyprowadzony<br />
w zależności od t max ,t min ,l max ,l min oraz t T ,l T . Dodatkowo <strong>na</strong>leży<br />
wprowadzić „bezpiecznik”, który będzie pilnował, żeby rozmiar dziennika nie<br />
został przekroczony:<br />
T ′ =min{T ′ ,T max }<br />
Formuła, która wyz<strong>na</strong>cza T ′ jest bardzo prostym prawem sterowania. Oczywiście<br />
taki sposób zarządzania dziennikiem wyda się trywialny dla kogoś, k<strong>to</strong><br />
z<strong>na</strong> dobrze zagadnienia sterowania, jed<strong>na</strong>k z praktycznego punktu widzenia <strong>to</strong><br />
podejście jest wystarczające, jeżeli tylko czasy wyko<strong>na</strong>nia rundy oraz długość<br />
dziennika nie zmieniają się zbyt gwał<strong>to</strong>wnie.<br />
Na rysunkach 4.8 oraz 4.9 pokazano przykład sterowania dla zmieniającego<br />
się czasu wyko<strong>na</strong>nia rundy. Sterowanie wskazuje co ile kroków <strong>na</strong>leży wyko<strong>na</strong>ć<br />
zapis stanu usługi. Rysunek 4.9 zawiera wyz<strong>na</strong>czone sterowanie dla losowo
4.5 Zatwierdzanie stanu 81<br />
35<br />
13<br />
12<br />
11<br />
30<br />
10<br />
9<br />
25<br />
8<br />
7<br />
20<br />
6<br />
15<br />
100 200 300 400 500 600 700 800 900 1000 1100<br />
5<br />
4<br />
0 100 200 300 400 500 600 700 800 900 1000 1100<br />
Rysunek 4.9: Sterowanie częs<strong>to</strong>ścią zapisu stanu (prawa stro<strong>na</strong>) dla zmieniającego<br />
się zakłóconego czasu wyko<strong>na</strong>nia usługi (lewa stro<strong>na</strong>) (L max = 100, t =<br />
20, δ=0.5).<br />
zmieniającego się czasu wyko<strong>na</strong>nia usługi.<br />
Pro<strong>to</strong>kół zatwierdzania stanu. Przedstawię teraz pro<strong>to</strong>kół synchronizacji i zatwierdzania<br />
stanu, który mógłby używać dowolnej me<strong>to</strong>dy wyz<strong>na</strong>czania kolejnej<br />
chwili migawki.<br />
1. Replika i po wyko<strong>na</strong>niu rundy wyz<strong>na</strong>cza za ile wyko<strong>na</strong>ń <strong>na</strong>stąpi synchronizacja<br />
T ′ i rozgłasza komunikat < schedule-request, i, T ′ > σi i czeka<br />
<strong>na</strong> 2f +1takich samych odpowiedzi od innych replik z uwzględnieniem<br />
siebie samej.<br />
2. Po odebraniu propozycji replika rozgłasza war<strong>to</strong>ść zatwierdzoną < scheduleresponse,<br />
i, ˆT >σi która jest war<strong>to</strong>ścią średnią ze wszystkich war<strong>to</strong>ści odpowiednio<br />
blisko war<strong>to</strong>ści proponowanej przez nią samą ˆT ≤ T j ± 10%.<br />
3. Replika co każdą rundę zapisuje stan (nie potwierdzony przez resztę replik),<br />
o ile ta operacja nie jest za bardzo pracochłon<strong>na</strong> .<br />
4. Po wyko<strong>na</strong>niu ˆT rund replika rozgłasza < checkpoint, ˆT , H(s), i>σi i<br />
czeka <strong>na</strong> 2f +1odpowiedzi uwzględniając ją samą.<br />
5. Zgromadzenie f +1podpisów dla s powoduje, że replika rozgłasza komunikat<br />
< checkpoint-commit, ˆT , H(s), i>σi oraz zatwierdza stan s<br />
podobnie jak <strong>to</strong> miało miejsce w przypadku pro<strong>to</strong>kołu BFT.<br />
6. Replika ponownie wyz<strong>na</strong>cza kolejny punkt synchronizacji T i rozgłasza<br />
komunikat schedule-request.<br />
Łatwo moż<strong>na</strong> zauważyć pewne usprawnienie, które polega <strong>na</strong> tym, że uzgadnianie<br />
kolejnego momentu zatwierdzenia stanu może odbyć się podczas bieżącej<br />
operacji zatwierdzania stanu, co z<strong>na</strong>cznie zmniejsza <strong>na</strong>kłady <strong>na</strong> komunikację.
82 Rozdział 4. Tolerowanie bizantyjskich uszkodzeń<br />
W tym paragrafie przedstawiłem pro<strong>to</strong>kół zatwierdzania stanu pokazując<br />
wcześniej, że brak uzgodnienia momentu zapisu mógłby doprowadzić do niepożądanego<br />
działania usługi. W uzupełnieniu do pro<strong>to</strong>kołu BFT został pokazany<br />
prosty sposób sterowania częs<strong>to</strong>ścią zapisu, który mógłby okazać się zawodny<br />
przy większych wymaganiach, jed<strong>na</strong>k stanowi rozwiązanie, które może zostać<br />
użyte po małych modyfikacjach w praktycznej realizacji.<br />
4.6 Pro<strong>to</strong>kół optymistyczny<br />
Twierdzenie o nie istnieniu konsensusu w całkowicie asynchronicznym systemie<br />
w obecności choć jednego nieuczciwie działającego procesu Fischera [FLP85]<br />
mówi o tym, że próba uzgadniania bez synchronizacji może nie przynieść rezultatu.<br />
Jed<strong>na</strong>k <strong>na</strong>dal istnieje szansa, że uzgadnianie się powiedzie. Pro<strong>to</strong>koły,<br />
które dopuszczają możliwość zaistnienia błędnego przebiegu przyjęło się <strong>na</strong>zywać<br />
pro<strong>to</strong>kołami optymistycznymi. W przypadku, gdy pro<strong>to</strong>kół optymistyczny<br />
zawiedzie wyko<strong>na</strong>nie zostaje przełączone w tryb użycia pro<strong>to</strong>kołu zachłannego.<br />
Opisywane w poprzednim rozdziale pro<strong>to</strong>koły BFT i SC-ABC posiadają swoje<br />
wersje optymistyczne. Pro<strong>to</strong>kół BF2 moż<strong>na</strong> również zmodyfikować w taki sposób,<br />
że zostanie wyeliminowa<strong>na</strong> duża część synchronizacji między replikami, a<br />
powrót do pro<strong>to</strong>kołu właściwego <strong>na</strong>stąpi podczas wykrycia błędów.<br />
• Wyko<strong>na</strong>nie pro<strong>to</strong>kołu BF2 w punkcie trzecim zakłada uzgodnienie przez<br />
repliki zbudowanego wek<strong>to</strong>ra R g . W pro<strong>to</strong>kole optymistycznym zamiast<br />
uzgadniać R g używając komunikatu request-ready <strong>na</strong>tychmiast przechodzimy<br />
do fazy wyko<strong>na</strong>nia zleceń.<br />
• Faza wyko<strong>na</strong>nia zlecenia może również zostać skróco<strong>na</strong>. W tym przypadku<br />
replika zapamiętuje stan obiektu sprzed wyko<strong>na</strong>nia zlecenia i wykonuje<br />
je <strong>na</strong>tychmiast, <strong>na</strong>stępnie rozgłasza komunikat pre-commit. Gdy<br />
pro<strong>to</strong>kół zawiedzie, replika wycofuje wyko<strong>na</strong>nie zlecenia.<br />
• Podążając za <strong>to</strong>kiem rozumowania z poprzedniego punktu, replika może<br />
wysłać odpowiedź do klienta od razu po wyko<strong>na</strong>niu zlecenia, jeżeli nie<br />
modyfikuje ono stanu usługi. Klient w przypadku odebrania za małej<br />
liczby takich samych odpowiedzi ponownie wyśle zlecenie ustawiając dodatkową<br />
flagę retrospect. Replika po odebraniu takiego zlecenia wie, że<br />
uprzednio wyko<strong>na</strong>nie nie powiodło się i <strong>na</strong>leży zrealizować całą operację<br />
z uwzględnieniem wszystkich kroków.<br />
Przełączenie w tryb wyko<strong>na</strong>nia pro<strong>to</strong>kołu zachłannego powinno <strong>na</strong>stępować<br />
zaraz po wykryciu niepoprawnego działania. Powrót do optymistycznego pro<strong>to</strong>-
4.7 Podsumowanie 83<br />
kołu może <strong>na</strong>stąpić wraz z rozpoczęciem wyko<strong>na</strong>nia nowej rudny, jed<strong>na</strong>k dopiero<br />
po uzgodnieniu wek<strong>to</strong>ra R g .<br />
4.7 Podsumowanie<br />
Pro<strong>to</strong>kół BF2, zaproponowany w tym rozdziale, jest przez<strong>na</strong>czony dla systemów<br />
rozproszonych, w których istnieje konieczność <strong>to</strong>lerowania uszkodzeń bizantyjskich,<br />
tzn. takich w których poszczególne elementy mogą zachowywać się w<br />
sposób arbitralny, a dy<strong>na</strong>mika zmiany struktury systemu jest bardzo duża. BF2<br />
jest podobny w wielu aspektach do pro<strong>to</strong>kołu BFT opisanego w poprzednim<br />
rozdziale 14 , jed<strong>na</strong>k różni się z<strong>na</strong>cząco w sposobie synchronizacji i uzgadniania<br />
zleceń do wyko<strong>na</strong>nia przez repliki.<br />
BFT przez<strong>na</strong>czony jest raczej dla systemów, które charakteryzują się statyczną<br />
strukturą. Podstawowym mechanizmem s<strong>to</strong>sowanym do ustalenia kolejności<br />
wyko<strong>na</strong>nia w BFT są widoki. W każdym widoku jeden z węzłów<br />
uczestniczących jest koordy<strong>na</strong><strong>to</strong>rem i do niego muszą być kierowane wszystkie<br />
zlecenia. Mechanizm widoków w BF2 został zastąpiony przez technikę wyko<strong>na</strong>nia<br />
zleceń w rundach, co jest usprawiedliwione przy dużej dy<strong>na</strong>mice grupy<br />
replik. Wyz<strong>na</strong>czanie koordy<strong>na</strong><strong>to</strong>ra użyte w BFT zakłada, że repliki są ponumerowane<br />
w ten sposób, że możliwe jest jednoz<strong>na</strong>czne ustalenie kolejnej repliki<br />
głównej, <strong>na</strong><strong>to</strong>miast w BF2 nie jest <strong>to</strong> wymagane.<br />
W tym rozdziale przedstawiono techniki konstrukcji grupy replik oraz pro<strong>to</strong>koły<br />
realizujące przyłączanie i odłączanie węzłów, czego nie specyfikuje ani<br />
BFT ani SC-ABC. Projekt pro<strong>to</strong>kołu został poszerzony o opis problemu zatwierdzania<br />
stanu, gdzie sformułowano problem sterowania częs<strong>to</strong>ścią zatwierdzania<br />
migawki i podano sprawne, choć może nie optymalne rozwiązanie.<br />
Podobnie jak w BFT oraz SC-ABC, w BF2 moż<strong>na</strong> zas<strong>to</strong>sować wersję optymistyczną<br />
pro<strong>to</strong>kołu, co w praktycznej realizacji powinno zwiększyć wydajność<br />
systemu, wtedy gdy środowisko pracy nie jest ekstremalnie nieprzychylne. Kolejny<br />
rozdział opisuje projekt systemu Pas<strong>to</strong>r, który implementuje algorytm BF2<br />
w jego podstawowej postaci.<br />
14 Dlatego przyję<strong>to</strong> oz<strong>na</strong>czenie BF2.
Rozdział 5<br />
Projekt systemu Pas<strong>to</strong>r<br />
Obiekty w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> podlegają replikacji z kilku powodów. Najważniejszy<br />
z nich związany jest ze swobodą odłączania i przyłączania się węzłów<br />
z i do systemu. Takie zachowanie elementów nie gwarantuje, że wprowadzone<br />
dane będą zawsze dostępne. Replikacja sprawia, że istnieją większe szanse, iż<br />
wprowadzone obiekty będą stale osiągalne. Drugi powód s<strong>to</strong>sowania replikacji<br />
wiąże się ze zwiększeniem dostępności obiektu. Replikacja w tym przypadku<br />
pozwala, by operacje odczytu obiektów były obsługiwane przez większą liczbę<br />
węzłów równolegle, co gwarantuje większą dostępność żądanych obiektów.<br />
W tym rozdziale został przedstawiony projekt i tes<strong>to</strong>wa wersja systemu Pas<strong>to</strong>r,<br />
który implementuje pro<strong>to</strong>kół BF2, oparty o sieć Pastry. W pierwszej części<br />
dokumentu zostały opisane dodatkowe techniki i me<strong>to</strong>dy, takie jak zarządzanie<br />
dostępem i postarzanie obiektów, konieczne do zas<strong>to</strong>sowania w oprogramowaniu.<br />
Dalsze fragmenty poświęcone są opisowi komponentów i konceptualnej<br />
struktury systemu. Ostatnie sekcje zawierają testy implementacji i ich a<strong>na</strong>lizę.<br />
5.1 Projekt systemu<br />
Pas<strong>to</strong>r jest rozszerzeniem Past (DHT), które realizuje replikację usługi (umożliwia<br />
zdalne wywołanie obiektów) opartym <strong>na</strong> Pastry, . Dla przypomnienia każdy<br />
węzeł w Pastry posiada unikalny identyfika<strong>to</strong>r o długości 160 bit. Po<strong>na</strong>d<strong>to</strong> obiekt<br />
umieszczony w sieci Pastry posiada identyfika<strong>to</strong>r, który wyz<strong>na</strong>czany jest jako<br />
skrót z zawar<strong>to</strong>ści przez bezkolizyjną jednokierunkową funkcją skrótu SHA-1<br />
lub w inny sposób zależny od oprogramowania. Pastry rzutuje identyfika<strong>to</strong>ry<br />
obiektów <strong>na</strong> identyfika<strong>to</strong>ry węzłów tak, że węzeł którego identyfika<strong>to</strong>r jest <strong>na</strong>jbliżej<br />
identyfika<strong>to</strong>ra obiektu używając miary euklidesowej, staje się za ten obiekt<br />
odpowiedzialny (patrz rozdział drugi). W razie konieczności obiekt jest replikowany<br />
w innych węzłach.
86 Rozdział 5. Projekt systemu Pas<strong>to</strong>r<br />
5.1.1 Język implementacji - Java<br />
Sieć Pastry została zaimplemen<strong>to</strong>wa<strong>na</strong> w języku Java, dlatego tes<strong>to</strong>wa realizacja<br />
Pas<strong>to</strong>ra jest realizowa<strong>na</strong> przy użyciu tego języka. Dokumentacja API systemu<br />
Pas<strong>to</strong>r w postaci standardowej dokumentacji Javadoc oraz źródła oprogramowania<br />
zostały umieszczone pod adresami (http://www.ia.pw.edu.pl/<br />
˜tkruk/students/lwalkiew/)oraz (http://www.ia.pw.edu.pl/<br />
˜lwalkiew/p2p/).<br />
Jak każdy język programowania Java ma swoje wady i zalety. Głównymi zaletami<br />
Javy jest niezależność od platformy sprzę<strong>to</strong>wej, dostępność zaawansowanych<br />
techniki programistycznych, takich jak serializacja obiektów, czy refleksja,<br />
w końcu duża liczba go<strong>to</strong>wych bibliotek zawartych w standardowej dystrybucji<br />
<strong>na</strong>rzędzi programistycznych Java JDK (ang. Java Development Kit.). Podstawową<br />
wadą Javy jest słaba wydajność. Wszystkie wyżej wymienione zalety<br />
stają się niemożliwe do wykorzystania przy projek<strong>to</strong>waniu skomplikowanego<br />
oprogramowania gdyż okazuje się, że większość bibliotek wymaga macierzystej<br />
implementacji zależnej od sprzętu JNI (ang. Java Native Interface.), by osiągnąć<br />
zadowalającą wydajność. Pomimo niedogodności Java jest świetną platformą do<br />
szybkiej implementacji, gdy głównym celem jest zbadanie właściwości i cech<br />
zaprojek<strong>to</strong>wanej architektury oprogramowania.<br />
Wyraźnym problemem dostrzeżonym w implementacji Pastry, rzutującym <strong>na</strong><br />
wydajność jest oparcie systemu <strong>na</strong> technice serializacji. Serializacja w dużym<br />
skrócie polega <strong>na</strong> takiej transformacji stanu obiektu, iż możliwym staje się przekazanie<br />
go do innej maszyny wirtualnej lub zapis <strong>na</strong> dysk, a <strong>na</strong>stępnie wyko<strong>na</strong>nie<br />
transformacji odwrotnej i dalsze użycie. Jest <strong>to</strong> bardzo wygodny mechanizm,<br />
gdyż w ten sposób możemy łatwo przesyłać dane między instancjami maszyny<br />
wirtualnej uruchomionymi <strong>na</strong> różnych maszy<strong>na</strong>ch za pośrednictwem sieci nietroszcząc<br />
się o reprezentacje, czy obsługę błędów, robi <strong>to</strong> za <strong>na</strong>s środowisko.<br />
W Pastry zas<strong>to</strong>sowano serializację do przesyłania między węzłami dosłownie<br />
wszystkiego, co niestety niekorzystnie wpływa <strong>na</strong> wydajność systemu. Każdy<br />
komunikat przed wysłaniem jest serializowany. Odebranie wiadomości w węźle<br />
pośrednim również wymaga deserializacji, dlatego użyta implementacja Pastry<br />
nie jest optymalnie wydaj<strong>na</strong>.<br />
5.1.2 Bezpieczeństwo wyko<strong>na</strong>nia<br />
Wyko<strong>na</strong>nie zlecenia przez węzeł po odebraniu komunikatu invoke stanowi wyraźne<br />
zagrożenie zarówno dla samej aplikacji <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, jak również sprzętu.<br />
Bezpieczne wyko<strong>na</strong>nie obcego kodu stanowi odrębne zagadnienie i nie będzie<br />
w tej pracy szeroko poruszane.<br />
Nie trudno sobie wyobrazić, jakie mogą być <strong>na</strong>stępstwa braku kontroli <strong>na</strong>d
5.1 Projekt systemu 87<br />
wyko<strong>na</strong>niem kodu niez<strong>na</strong>nego pochodzenia. Załóżmy, że obiekt, jaki został<br />
wprowadzony do systemu, posiada me<strong>to</strong>dę która buduje potajemnie kod wykonywalny<br />
będący wirusem, zapisuje go <strong>na</strong> dysku ofiary, a <strong>na</strong>stępnie uruchamia.<br />
Inny sce<strong>na</strong>riusz możliwy do zaistnienia, zakłada, że obiekt rozsyła swoje kopie<br />
do wszystkich węzłów, które z<strong>na</strong> ofiara działając jak robak używający aplikacji<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, jako medium do rozprzestrzeniania.<br />
Zasyg<strong>na</strong>lizuję problemy, jakie <strong>na</strong>leży rozwiązać, by zagwaran<strong>to</strong>wać pewien<br />
poziom bezpieczeństwa i kontroli <strong>na</strong>d wykonywanym kodem niez<strong>na</strong>nego pochodzenia:<br />
• Kod zewnętrznego pochodzenia powinien być podpisany, a podpis możliwy<br />
do weryfikacji.<br />
• Kod zewnętrznego pochodzenia powinien zostać zweryfikowany zanim<br />
umożliwi się jego wyko<strong>na</strong>nie.<br />
• Każde wywołanie me<strong>to</strong>dy obcego obiektu powinno odbywać się pod kontrolą,<br />
<strong>na</strong>jlepiej w osobnym wątku, z pełnym <strong>na</strong>dzorem <strong>na</strong>d zamawianymi<br />
zasobami systemu operacyjnego, jak i dostępu do obiektów wewnątrz aplikacji.<br />
Badania prowadzone <strong>na</strong>d bezpieczeństwem wyko<strong>na</strong>nia doprowadziły do opracowania<br />
dwóch modeli wyko<strong>na</strong>nia obcego kodu: piaskownicy (ang. sandbox)<br />
i placu zabaw (ang. playgroud). Piaskownica polega <strong>na</strong> tym, że środowisko<br />
wyko<strong>na</strong>nia określa sztywno jakie operacje mogą być wyko<strong>na</strong>ne przez obcy kod<br />
i każde <strong>na</strong>ruszenie tych ograniczeń poskutkuje zatrzymaniem wyko<strong>na</strong>nia i zgłoszeniem<br />
wyjątku. Plac zabaw dla odmiany jest trochę mniej restrykcyjnym rozwiązaniem,<br />
które zezwala <strong>na</strong> wyko<strong>na</strong>nie niektórych uprzywilejowanych operacji,<br />
gdy tylko polityka bezpieczeństwa <strong>na</strong>rzuca<strong>na</strong> przez aplikację akceptuje takie zachowanie,<br />
np. możemy by obcy obiekt <strong>na</strong>wiązywał połączenia ze źródłem, z<br />
którego został pobrany. Przed rozpoczęciem wyko<strong>na</strong>nia obcego kodu aplikacja<br />
powin<strong>na</strong> z<strong>na</strong>ć wszystkie zasoby, z których ten kod będzie korzystał. Różnica<br />
między piaskownicą i placem zabaw jest taka, że w przypadku placu zabaw do<br />
obcego kodu może zostać dołączo<strong>na</strong> lista zasobów niezbędnych do jego wyko<strong>na</strong>nia<br />
i aplikacja może zdecydować czy te zasoby mogą być udostępnione <strong>na</strong><br />
czas wyko<strong>na</strong>nia. Obecnie termin placu zabaw jest wypierany przez określenie<br />
piaskownica, chociaż au<strong>to</strong>rzy pisząc o piaskownicy <strong>na</strong>jczęściej mają <strong>na</strong> myśli<br />
placu zabaw.<br />
Implementacja Pastry i Pas<strong>to</strong>ra została wyko<strong>na</strong><strong>na</strong> w języku Java, który pozwala<br />
<strong>na</strong> rozwiązanie powyższych zagadnień bespieczeństawa, ale tyko częściowo.<br />
Na chwilę pisanie tego dokumentu obowiązującym standardem było<br />
J2SE 5.0, które nie implementuje mechanizmów kontroli kodu <strong>na</strong> poziomie
88 Rozdział 5. Projekt systemu Pas<strong>to</strong>r<br />
obiektu, dlatego też wszystkie zabezpieczenia musiałyby być zrealizowane <strong>na</strong><br />
poziomie wątku wyko<strong>na</strong>nia, co dodatkowo rzutuje <strong>na</strong> wydajność. Wymagania<br />
zapewnienia bezpieczeństwa moż<strong>na</strong> rozwiązać używając dwóch podejść:<br />
• Weryfikacja typu off-line, tzn. architektura aplikacji powin<strong>na</strong> wykorzystywać<br />
mechanizm wtyczek (ang. plug-in), które dostarczane są z wiadomego<br />
źródła, jako zewnętrzne klasy. Uruchamiane klasy powinny być podpisane,<br />
a ich uprawnienia zależne od polityki bezpieczeństwa. Niestety <strong>to</strong> podejście<br />
ogranicza możliwość przechowania, niektórych obiektów przez węzeł,<br />
gdyż mogą one nie mieć wbudowanej odpowiedniej wtyczki. Wytłumaczenie<br />
powyższej sytuacji wymaga posłużenia się przykładem: Węzeł u chce<br />
umieścić w sieci obiekt klasy A o identyfika<strong>to</strong>rze A id . Wykonuje operację<br />
insert, która przesyła obiekt poprzez sieć do celu, którego identyfika<strong>to</strong>r<br />
jest <strong>na</strong>jbliższy względem A id . Przyjmijmy, że punktem docelowym będzie<br />
węzeł v. Jeżeli v posiada wtyczkę zawierającą plik A.class, <strong>to</strong>używając<br />
deserializacji poprawnie odbierze obiekt A i umieści go w swojej pamięci<br />
trwałej. W przeciwnym razie próba rozpakowania obiektu A nie powiedzie<br />
się i zostanie zgłoszony wyjątek.<br />
• Weryfikacja on-line zakłada, że definicje klas są pobierane w sposób dy<strong>na</strong>miczny<br />
i uruchomienie obiektów odbywa się w przygo<strong>to</strong>wanym i <strong>na</strong>dzorowanym<br />
środowisku (np. piaskownicy). To podejście jest z<strong>na</strong>cznie trudniejsze<br />
do zaimplemen<strong>to</strong>wania, ale nie <strong>na</strong>kłada ograniczeń co do możliwości<br />
przechowywania konkretnych obiektów przez określony węzeł. Wrócę do<br />
poprzedniego przykładu. Węzeł u <strong>na</strong>dal chce przesłać obiekt A do węzła<br />
u. W tym celu u opakowuje A oraz zawar<strong>to</strong>ść pliku A.class w jeden<br />
obiekt Content, którego klasa z<strong>na</strong><strong>na</strong> jest obu węzłom. Po<strong>na</strong>d<strong>to</strong> obiekt Content<br />
implementuje dwie me<strong>to</strong>dy put oraz get, które pozwalają „upakować”<br />
przesyłane obiekty w standardowych tablicach bajtów. Gdy Content dotrze<br />
do v ten rozpakuje <strong>na</strong>jpierw plik A.class i wczyta go używając własnego<br />
SecureClassLoader’a, który ustawi ograniczenia dla tego obiektu.<br />
W początkowej implementacji systemu Pas<strong>to</strong>r zostały użyte elementy weryfikacji<br />
off-line oraz on-line. Obiekty w obecnej implementacji Pas<strong>to</strong>ra wysyłane<br />
są w specjalnym kontenerze Content, ale bez dołączonej definicji klasy. Definicje<br />
pobierane są z wtyczek, które muszą zostać umieszczone w katalogu plugin/<br />
w pliku jar.<br />
Więcej informacji <strong>na</strong> temat bezpieczeństwa w Java 2 czytelnik z<strong>na</strong>jdzie w<br />
książce Li Gonga [Gon99].
5.1 Projekt systemu 89<br />
5.1.3 Postarzanie obiektów<br />
Użyteczną techniką s<strong>to</strong>sowaną przez DHT zaimplemen<strong>to</strong>wanym w systemie Kademlia<br />
jest postarzanie obiektów [MM02]. Wcześniej ta technika była s<strong>to</strong>sowa<strong>na</strong><br />
<strong>na</strong> przykład w systemie plików rozproszonego systemu operacyjnego Amoeba<br />
[Tan95], aczkolwiek użycie tej techniki w systemie Amoeba miało zupełnie inne<br />
przesłanki, niż ma <strong>to</strong> miejsce w Kademlii. W Amoebie postarzanie wiązało się<br />
z usuwaniem nieużywanych już plików, do których nie odnosi się żad<strong>na</strong> ścieżka<br />
dojścia 1 , starsze pliki, niż pew<strong>na</strong> ustalo<strong>na</strong> war<strong>to</strong>ść były kasowane. Kademlia implementuje<br />
podobny mechanizm. Użytkownik chcąc, by jego obiekt pozostał w<br />
DHT Kademlii musi wywołać przy<strong>na</strong>jmniej raz <strong>na</strong> dobę operację odświeżania,<br />
co odpowiada operacji dotknięcia (ang. <strong>to</strong>uch) s<strong>to</strong>sowanej w systemie Amoeba.<br />
Przesłanki, jakie kierowały projektantami Kademlii wiązały się z rozsądnym gospodarowaniem<br />
przestrzenią dyskową, chociaż przyjęty czas przeterminowania<br />
obiektu, czyli doba, wydaje się być trudny do interpretacji.<br />
W systemie Pas<strong>to</strong>r, postarzanie obiektów moż<strong>na</strong> usprawiedliwić nie tylko<br />
optymalizacją zaję<strong>to</strong>ści przestrzeni dyskowej, ale też wydatkami komunikacyjnymi<br />
<strong>na</strong> utrzymywanie stanu replik dla obiektów, które nie są więcej wywoływane.<br />
FreePastry posiada rozszerzenie GCPast (ang. Garbage Collec<strong>to</strong>r Past),<br />
które implementuje usuwanie obiektów dlatego Pas<strong>to</strong>r opierał się <strong>na</strong> tym rozszerzeniu.<br />
Implementacja FreePastry<br />
Do realizacji oprogramowania uży<strong>to</strong> wersji FreePastry 1.4.1 (maj 2005), w skład<br />
której wchodzą <strong>na</strong>stępujące komponenty:<br />
• Pastry - substrat <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>.<br />
• Past - implementacja DHT.<br />
• Scribe - mechanizm komunikacji grupowej.<br />
• Glacier - współdzielenie zawar<strong>to</strong>ści (podobne do pro<strong>to</strong>kołu BitTorrent).<br />
• SplitStream - strumieniowe przesyłanie danych.<br />
Jest <strong>to</strong> duża baza, która pozwala <strong>na</strong> skonstruowanie <strong>na</strong>wet bardzo wyszukanych<br />
aplikacji rozproszonych. W tym rozdziale nie będę dokładnie opisywał<br />
interfejsu programistycznego dostarczanego przez FreePastry, gdyż przedstawienie<br />
funkcjo<strong>na</strong>lności tego oprogramowania wykracza daleko poza ramy tej pracy<br />
1 Serwer pików periodycznie odświeżał z<strong>na</strong>czniki czasu do plików, do których istniały dojścia<br />
w systemie katalogowym.
90 Rozdział 5. Projekt systemu Pas<strong>to</strong>r<br />
i <strong>to</strong> zagadnienie mogłoby stanowić oddzielne opracowanie. Dokumentację w<br />
postaci plików Javadoc do biblioteki FreePastry czytelnik z<strong>na</strong>jdzie <strong>na</strong> załączonej<br />
płycie CD. Jedynie w celach ilustracji został podany przykład wraz z komentarzem,<br />
utworzenia węzła sieci Pastry (listing 5.1), oraz zarejestrowania zawar<strong>to</strong>ści<br />
w Past (listing 5.2).<br />
Listing 5.1: Tworzenie instancji węzła w Past.<br />
1 // Nazwa instancji aplikacji<br />
2 String instance = new String("PastTesT");<br />
3<br />
4 // Liczba replik dla obiektu Past<br />
5 int replicas = 3;<br />
6<br />
7 // Port przyłączenia<br />
8 int bindport = 6666;<br />
9<br />
10 // Adres przyłączenia<br />
11 InetSocketAddress bootaddress =<br />
12 new InetSocketAddress("127.0.0.1", bindport);<br />
13<br />
14 // Klasa budowy losowych identyfika<strong>to</strong>rów<br />
15 PastryIdFac<strong>to</strong>ry nidFac<strong>to</strong>ry =<br />
16 new RandomNodeIdFac<strong>to</strong>ry();<br />
17<br />
18 // Klasa budowy węzłów dla połączeń sieciowych<br />
19 PastryNodeFac<strong>to</strong>ry fac<strong>to</strong>ry =<br />
20 new SocketPastryNodeFac<strong>to</strong>ry(nidFac<strong>to</strong>ry, bindport);<br />
21<br />
22 // Uchwyt do węzła przyłączenia<br />
23 NodeHandle bootHandle =<br />
24 ((SocketPastryNodeFac<strong>to</strong>ry)fac<strong>to</strong>ry).getNodeHandle(bootaddress);<br />
25<br />
26 // Utworzenie nowego węzła<br />
27 PastryNode node = fac<strong>to</strong>ry.newNode((NodeHandle) bootHandle);<br />
28<br />
29 // Klasa tworzenia identyfika<strong>to</strong>rów węzłów<br />
30 NodeIdFac<strong>to</strong>ry Idf = new PastryIdFac<strong>to</strong>ry();<br />
31<br />
32 // Utworzenie zarządcy obiektami przestrzeni ok. 1MB<br />
33 S<strong>to</strong>rageMa<strong>na</strong>gerImpl s<strong>to</strong>rage =<br />
34 new S<strong>to</strong>rageMa<strong>na</strong>gerImpl(Idf,<br />
35 new PersistentS<strong>to</strong>rage(Idf, "root", ".", 1000000),<br />
36 new LRUCache(new MemoryS<strong>to</strong>rage(Idf), 100000));<br />
37<br />
38 // Utworzenie obiektu aplikacji Past<br />
39 Past past = new PastImpl(node, s<strong>to</strong>rage, replicas, instance);<br />
Utworzenie węzła inicjuje wywołanie me<strong>to</strong>dy getNodeHandle(bootaddress)<br />
klasy SocketNodeFac<strong>to</strong>ry, co ma <strong>na</strong> celu pobranie uchwytu do węzła przyłączającego.<br />
Gdy węzeł przyłączający nie odpowie uchwyt bootHandle będzie<br />
miał war<strong>to</strong>ść null, wtedy zostanie utworzo<strong>na</strong> nowa sieci Pastry poprzez wywoałnie<br />
me<strong>to</strong>dy newNode(bootHandle). W innym przypadku węzeł zostanie<br />
przyłączony poprzez węzeł o adresie bootaddress do istniejącej sieci. Kolejnym<br />
krokiem jest utworzenie zarządcy przestrzeni trwałej S<strong>to</strong>rageMa<strong>na</strong>gerImpl o<br />
wielkości około 1MB. W końcu do życia powołuje się instancję węzła aplikacji<br />
Past.<br />
Listing 5.2: Wprowadzanie obiektu do Past.<br />
1 // Tworzymy obiekt o, który zostanie wprowadzony do sieci<br />
2 String str = new String("Nowy obiekt");<br />
3
5.1 Projekt systemu 91<br />
4 MyPastContent myObject =<br />
5 new MyPastContent(Idf.buildId(str.<strong>to</strong>String()), str);<br />
6<br />
7 // Wprowadzamy obiekt do sieci<br />
8 past.insert(myObject, new Continuation() {<br />
9 public void receiveResult(Object o) {<br />
10 System.out.println("Got result " + o);<br />
11 }<br />
12 public void receiveException(Exception e) {<br />
13 System.out.println("Oops! An error occurred: " + e);<br />
14 }<br />
15 });<br />
16<br />
17 Thread.sleep(1000);<br />
18<br />
19 // Wyszukujemy obiekt<br />
20 past.lookup(myObject.getId(), new Continuation() {<br />
21 public void receiveResult(Object o) {<br />
22 System.out.println("Got result " + o);<br />
23<br />
24 }<br />
25 public void receiveException(Exception e) {<br />
26 System.out.println("Oops! An error occurred: " + e);<br />
27 }<br />
28 });<br />
Wprowadzenie zawar<strong>to</strong>ści do Past jest trochę trudniejsze, gdyż użycie operacji<br />
insert skutkuje utworzeniem dodatkowego wątku przetważania poprzez użycie<br />
anonimowej klasy wewnętrznej Continuation, który realizuje zlecenie działając<br />
„w tle”, czyli asynchronicznie z punktu widzenia użytkownika. W pierwszej kolejności<br />
utworzony zostaje obiekt klasy MyPastContent, którego identyfika<strong>to</strong>r<br />
jest zbudowany przez obiekt fabryki identyfika<strong>to</strong>rów Idf typu NodeIdFac<strong>to</strong>ry <strong>na</strong><br />
podstawie ciągu z<strong>na</strong>ków str. Następnie wywoływa<strong>na</strong> zainicjowanej instancji węzła<br />
past. Wywoływanie podstawowych operacji nie jest wielce skomplikowane,<br />
gdyż oprogramowanie FreePastry ma s<strong>to</strong>sunkowo intuicyjny i prosty interfejs<br />
programistyczny.<br />
Komponenty<br />
Pas<strong>to</strong>r - aplikacja działająca w oparciu o sieć Pastry dostarczająca me<strong>to</strong>dy<br />
invoke i dziedzicząca inne operacje po GCPast.<br />
Pas<strong>to</strong>rContent - specjalny rodzaj obiektu, który dziedziczy po PastContent,<br />
ale umożliwia dodatkowo wykonywanie me<strong>to</strong>d.<br />
Pas<strong>to</strong>rContentHandle - uchwyt do obiektu Pas<strong>to</strong>rContent, np. pozwala<br />
określić węzeł, z którego pochodzi.<br />
Messanger - interfejs umożliwiający rozgłaszanie komunikatów z zachowaniem<br />
warunku przyczynowości.<br />
Replica<strong>to</strong>r - aplikacja działająca w oparciu o sieć Pastry, podobnie jak<br />
Pas<strong>to</strong>r. Jej zadaniem jest wykonywanie i obsługa zleceń zgłaszanych przez<br />
aplikację Pas<strong>to</strong>r.
92 Rozdział 5. Projekt systemu Pas<strong>to</strong>r<br />
Wywołanie me<strong>to</strong>dy obiektu w Pas<strong>to</strong>rze odbywa się podobnie, jak w Past.<br />
Klient określa id obiektu, który będzie wywołany, buduje obiekt zlecenia, które<br />
przyjmuje jako parametr <strong>na</strong>zwę me<strong>to</strong>dy do wywołania oraz argumenty wyołania.<br />
Klient podczas wywołania operacji invoke tworzy obiekt kontynuacji (Continuation)<br />
i czeka <strong>na</strong> odpowiedź.<br />
Listing 5.3: Utworzenie węzła Pas<strong>to</strong>ra oraz wywołanie obiektu.<br />
1 // Tworzymy nową fabrykę identyfika<strong>to</strong>rów<br />
2 PastryIdFac<strong>to</strong>ry f = new PastryIdFac<strong>to</strong>ry();<br />
3<br />
4 // Inicjujemy zarządcę przestrzenią dyskową<br />
5 S<strong>to</strong>rageMa<strong>na</strong>gerImpl s<strong>to</strong>rage = new S<strong>to</strong>rageMa<strong>na</strong>gerImpl(f,<br />
6 new PersistentS<strong>to</strong>rage(f, "root", ".", 1000000),<br />
7 new LRUCache(new MemoryS<strong>to</strong>rage(f), 100000));<br />
8<br />
9 // Tworzymy węzeł aplikacji Pas<strong>to</strong>r używając węzła - node sieci Pastry<br />
10 Pas<strong>to</strong>r pas<strong>to</strong>r = new Pas<strong>to</strong>rImpl(node, s<strong>to</strong>rage, REPLICATION_FACTOR,<br />
11 INSTANCE, new PastPolicy.DefaultPastPolicy(),<br />
12 GCPast.INFINITY_EXPIRATION);;<br />
13<br />
14 // Tworzymy obiekt Obj i wywołujemy lokalnie me<strong>to</strong>dę setString<br />
15 Obj o = new Obj();<br />
16 o.setString("Alice has a kitty.");<br />
17<br />
18 // Tworzymy obiekt aplikacji Pas<strong>to</strong>r<br />
19 Pas<strong>to</strong>rContent myObject = new Pas<strong>to</strong>rContent(f.buildId("Nowy obiekt"), o);<br />
20<br />
21 // Obiekt zostaje umieszczony w sieci<br />
22 pas<strong>to</strong>r.insert(myObject, new Continuation() {<br />
23 public void receiveResult(Object o) {<br />
24 System.out.println("Got result " + o.<strong>to</strong>String());<br />
25 }<br />
26 public void receiveException(Exception e) {<br />
27 System.out.println("Oops! An error occurred: " + e);<br />
28 }<br />
29 });<br />
30<br />
31 Thread.sleep(2000);<br />
32<br />
33 // Tworzymy nowe parametry wywołania<br />
34 Object[] params = new Object[] { new String("Kitty has Alice.") };<br />
35<br />
36 // Tworzymy obiekt zlecenia wywołania me<strong>to</strong>dy setString<br />
37 Command cmd = new CommandContent(1, "setString", params);<br />
38<br />
39 // Wywołujemy me<strong>to</strong>dę obiektu uprzednio umieszczonego w sieci.<br />
40 // W wyniku powinniśmy otrzymać <strong>na</strong>pis "Alice has a kitty.", gdyż<br />
41 // me<strong>to</strong>da setString zwraca uprzednio zapamiętany ciąg z<strong>na</strong>ków.<br />
42 pas<strong>to</strong>r.invoke(f.buildId("Nowy obiekt"), cmd, new Continuation() {<br />
43 public void receiveResult(Object o) {<br />
44 System.out.println("Got result " + o.<strong>to</strong>String());<br />
45 }<br />
46 public void receiveException(Exception e) {<br />
47 System.out.println("Oops! An error occurred: " + e);<br />
48 }<br />
49 });<br />
Przykład utworzenia węzła Pas<strong>to</strong>r’a oraz wywołanie obiektu umieszczono <strong>na</strong><br />
listigu 5.3.<br />
5.1.4 Zarządzanie dostępem<br />
Zarządzanie uprawnieniami klientów moż<strong>na</strong> zrealizować używając kryp<strong>to</strong>grafii<br />
z kluczem publicznym. Nie jest <strong>to</strong> może idealne rozwiązanie ze względu <strong>na</strong>
5.1 Projekt systemu 93<br />
wydajność, jed<strong>na</strong>k przemawia za tym wiele aspektów.<br />
Użytkownik wprowadzając obiekt o do systemu generuje parę kluczy: K p ,K s .<br />
K p jest kluczem publicznym, <strong>na</strong><strong>to</strong>miast K s jest kluczem prywatnym. Klucz publiczny<br />
zostaje dołączony do obiektu i wprowadzony do systemu, tak że każda<br />
replika obiektu będzie również posiadała jego klucz publiczny. Klucz prywatny<br />
posłuży do wygenerowania uprawnień (ang. credentials). Uprawnienia mogą<br />
być przyz<strong>na</strong>wane <strong>na</strong> rzecz wszystkich (publiczne), grupy oraz indywidualnego<br />
użytkownika, podobnie jak ma <strong>to</strong> miejsce w systemie Linux.<br />
Uprawnienia publiczne dołączane są do wprowadzanego obiektu. Poniżej<br />
umieszczono opis tworzenia i weryfikacji uprawnień:<br />
1. s u = K s (H(o), u,c,Kp u ) - użytkownik wystawia uprawnienie c <strong>na</strong> rzecz<br />
obiektu o dla użytkownika u, Kp<br />
u jest kluczem publicznym użytkownika<br />
u. Należy zauważyć, że uprawnienie c może mieć dowolną postać, może<br />
być <strong>na</strong>daniem praw do wyko<strong>na</strong>nia tylko jednej konkretnej operacji, lub<br />
całego ich zestawu. Warunek jest tylko taki, aby postać c była zrozumiała<br />
dla usługi.<br />
2. insert(H(o), o,K p ) - wprowadzenie obiektu o do systemu musi odbywać<br />
się wraz z wprowadzeniem klucza weryfikacyjnego K p .<br />
3. Pro<strong>to</strong>kół używa me<strong>to</strong>dy typu challenge-response do zapewnienia jednorazowego<br />
użycia uprawnień. Niech r oz<strong>na</strong>cza losowo wygenerowaną liczbę,<br />
którą replika wysyła do użytkownika, gdy ten chce wyko<strong>na</strong>ć operację <strong>na</strong><br />
usłudze. Użytkownik generuje bilet (ang. ticket) t = Ks u (r, s c ) iwysyła<br />
operację zawierającą bilet do repliki (H(o), c, u, r, s c , t, Kp u ). Bilet<br />
będzie honorowany przez replikę, tak długo jak będzie <strong>to</strong> ustalone (np.<br />
przez określoną ilość operacji lub czasu).<br />
4. W celu ustalenia uprawnień użytkownika, replika weryfikuje s c używając<br />
K p , a <strong>na</strong>stępnie weryfikuje bilet t używając K u p .<br />
W przypadku weryfikacji uprawnień dla grupy, proces przebiega prawie tak<br />
samo z tym wyjątkiem, że u staje się identyfika<strong>to</strong>rem grupy g, a klucz użyty do<br />
wyz<strong>na</strong>czenia w uprawnienia w punkcie 1. staje się Kp<br />
g i przestaje <strong>na</strong>leżeć do<br />
jednego uczestnika, tylko do wszystkich uczestników w grupie. Głów<strong>na</strong> różnica<br />
polega <strong>na</strong> obsłudze jednorazowych biletów. Bilet <strong>na</strong>dal musi być wystawiony <strong>na</strong><br />
rzecz konkretnego użytkownika, dlatego bilet wyz<strong>na</strong>czany jest przy użyciu Kp u .<br />
Podany schemat weryfikacji dostępu działa tak długo, jak klucz prywatny<br />
K s wstawiającego obiekt nie zostanie złamany lub przechwycony, oraz gdy któryś<br />
z kluczy prywatnych uczestników nie zostanie złamany lub przechwycony.
94 Rozdział 5. Projekt systemu Pas<strong>to</strong>r<br />
Pierwszy przypadek całkowicie blokuje usługę, drugi sprawia, że atakujący będzie<br />
miał taki dostęp do obiektu, jaki miał zagwaran<strong>to</strong>wany użytkownik, którego<br />
klucz prywatny udało mu się złamać lub przywłaszczyć.<br />
W pierwszym przypadku wystawiający uprawnienia musi unieważnić klucz<br />
weryfikacyjny, <strong>na</strong><strong>to</strong>miast w drugiej sytuacji uprawnienie musi zostać wystawione<br />
ponownie, z nowym kluczem publicznym użytkownika. Niestety w tym schemacie<br />
nie ma możliwości łątwego cofnięcia uprzednio wystawionego uprawnienia.<br />
Jedy<strong>na</strong> możliwość, <strong>to</strong> bezpośrednia interwencja wystawiającego, który oz<strong>na</strong>jmia,<br />
że konkretne uprawnienie zostało cofnięte (zostaje utworzo<strong>na</strong> lista cofnięć).<br />
5.2 Podsumowanie<br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> stają się coraz bardziej popularne ze względu <strong>na</strong> rosnącą<br />
liczbę implementacji aplikacji opartych <strong>na</strong> ich architekturze. Liczba możliwych<br />
zas<strong>to</strong>sowań tej klasy systemów jest bardzo długa, chociaż niektóre zas<strong>to</strong>sowania,<br />
takie jak obliczenia rozproszone wymagają jeszcze wielu badań i a<strong>na</strong>liz.<br />
Istnieją pewne specyficzne zas<strong>to</strong>sowania np. maskowanie usługi i trasowanie<br />
cebulkowe, które byłyby bardzo trudne do realizacji przy użyciu klasycznych<br />
aplikacji sieciowych.<br />
Wśród s<strong>to</strong>sowanych aplikacji typu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> dominują nieustrukturalizowane<br />
architektury które są łatwe w budowie, chociaż wykorzystują punkty centralne.<br />
Łatwiejsze w a<strong>na</strong>lizie i konstrukcji są architektury ustrukturalizowane<br />
oparte <strong>na</strong> algorytmie przedrostkowego trasowania komunikatów Plax<strong>to</strong><strong>na</strong>. Niestety<br />
<strong>na</strong> chwilę pisania tej pracy brakowało aparatu teoretycznego przez<strong>na</strong>czonego<br />
do formalnej a<strong>na</strong>lizy tych systemów, a szczególnie ich dy<strong>na</strong>micznego zachowania.<br />
Zagadnienie, które zostało przea<strong>na</strong>lizowane w kontekście systemów luźno powiązanych<br />
dotyczy <strong>to</strong>lerancji <strong>na</strong> uszkodzenia, a dokładnie arbitralne zachowanie<br />
elementów. Przedstawiono dwa algorytmy bezpiecznej replikacji usługi <strong>to</strong>lerującej<br />
<strong>bizantyjskie</strong> uszkodzenia, BFT (B. Liskov i M. Castro, MIT) oraz SC-ABC<br />
(K. Kursawe i V. Schoup, IBM). Zasadniczy problem obu podejść wynika bądź<br />
<strong>to</strong> ze wskazania elementu centralnego, który <strong>na</strong>dzoruje wyko<strong>na</strong>nie usługi, tak<br />
jak ma <strong>to</strong> miejsce w BFT, lub trudności w zarządzaniu składem grupy, co z kolei<br />
ma miejsce w SC-ABC. Próbą rozwiązania tych problemów jest zaproponowany<br />
w rozdziale czwartym algorytm BF2.<br />
W ostatnim rozdziale przedstawiono projekt systemu Pas<strong>to</strong>r, rozszerzenia do<br />
ustrukturalizowanego systemu <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> Pastry, a dokładniej do aplikacji Past<br />
opartej <strong>na</strong> Pastry, czyli rozproszonej tablicy z kodowaniem mieszającym. Pas<strong>to</strong>r<br />
wprowadza do Past możliwość zdalnego wywoływania obiektów przechowywanych<br />
w systemie i zapewnia odporność <strong>na</strong> <strong>bizantyjskie</strong> zachowanie węzłów, które
5.2 Podsumowanie 95<br />
wchodzą w skład grupy replikującej obiekt.<br />
Do opracowania pozostaje wnikliwa a<strong>na</strong>liza algorytmu BF2 oraz teoretycz<strong>na</strong><br />
weryfikacja jego poprawności, np. w oparciu o teorię au<strong>to</strong>matów lub sieci Petriego.<br />
Praktycz<strong>na</strong> implementacja oprogramowania powin<strong>na</strong> być rozwija<strong>na</strong>, aż<br />
do momentu wprowadzenia wszystkich zaproponowanych rozwiązań.<br />
Systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> będą coraz częściej używanym oprogramowaniem sieciowym.<br />
Popularność, którą zdobyły zarówno wśród użytkowników, jak i środowiska<br />
<strong>na</strong>ukowego głównie w USA <strong>na</strong> chwilę obecną sugeruje, że aplikacje tego<br />
typu będą <strong>na</strong>dal mocno rozwijane i badane. Niestety głównym zas<strong>to</strong>sowaniem<br />
systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> <strong>na</strong>jprawdopodobniej pozostanie wymia<strong>na</strong> plików między<br />
użytkownikami globalnej sieci, jaką jest Internet 2 .<br />
2 Amerykański sąd <strong>na</strong>jwyższy w dniu 28 czerwca 2005 roku uz<strong>na</strong>ł, że serwisy wymiany plików<br />
mogą być pozywane za <strong>na</strong>ruszenie praw au<strong>to</strong>rskich, o ile sugerują użytkownikom wymianę<br />
materiału chronionego prawnie. (źródło: CNN.)
Dodatek A<br />
Elementy teorii grafów<br />
Teoria grafów jest jednym z <strong>na</strong>rzędzi projek<strong>to</strong>wania systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Szczególne<br />
z<strong>na</strong>czenie <strong>na</strong> początku projek<strong>to</strong>wania ma wybór odpowiedniej architektury,<br />
jaką powinien mieć system, by uzyskać jak <strong>na</strong>jmniejsze odległości między węzłami<br />
w przestrzeni identyfika<strong>to</strong>rów i jednocześnie utrzymywać, jak <strong>na</strong>jmniejszą<br />
liczbę połączeń przez poszczególne węzły. Ważnym aspektem jest spójność krawędziowa<br />
i wierzchołkowa sieci, która stanowi, o tym jak bardzo system <strong>peer</strong>-<strong>to</strong><strong>peer</strong><br />
będzie odporny <strong>na</strong> niespodziewane odłączanie poszczególnych węzłów lub<br />
ich niepoprawne działanie. Pożądaną właściwością jest istnienie wielu dróg rozłącznych<br />
krawędziowo i wierzchołkowo pomiędzy węzłami, gdyż w przypadku<br />
wystąpienia problemów podczas wysyłania komunikatu, powin<strong>na</strong> istnieć in<strong>na</strong><br />
droga, którą moż<strong>na</strong> przesłać wiadomość. Niestety <strong>na</strong> chwilę obecną brakuje<br />
sformalizowanej me<strong>to</strong>dyki, która pozwalałaby <strong>na</strong> a<strong>na</strong>lizę dy<strong>na</strong>micznych właściwości<br />
grafów sieci <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>.<br />
Przedstawię kilka podstawowych faktów z teorii grafów, które z<strong>na</strong>jdują bezpośrednie<br />
zas<strong>to</strong>sowanie przy projek<strong>to</strong>waniu systemów <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. W pierwszej<br />
kolejności zostanie podane kilka definicji, a <strong>na</strong>stępnie <strong>na</strong>jczęściej używane architektury<br />
grafowe występujące w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>.<br />
Definicja. Grafem G <strong>na</strong>zywamy zbiór G(V,E), gdzie V <strong>na</strong>zwany jest zbiorem<br />
wierzchołków, <strong>na</strong><strong>to</strong>miast E zbiorem krawędzi. Mówi się, że krawędź e ∈ E<br />
jest incydent<strong>na</strong> do wierzchołka v ∈ V , gdy e jest przylega do v. Krawędź e<br />
musi być przyległa do jakiegoś wierzchołka obustronnie. Grafy reprezentuje się<br />
<strong>na</strong>jczęściej w postaci rysunków, takich jak rysunek A.1.<br />
Definicja. S<strong>to</strong>pniem wierzchołka v <strong>na</strong>zywamy liczbę krawędzi incydentnych do<br />
tego wierzchołka i oz<strong>na</strong>czamy d(v).<br />
Definicja. Drogą z wierzchołka v 1 do v n w grafie <strong>na</strong>zywamy uporządkowany
98 Dodatek A. Elementy teorii grafów<br />
zbiór krawędzi i wierzchołków {v 1 e 1 v 2 e 2 ...e n v n }, w którym pierwszym elementem<br />
jest wierzchołek v 1 , <strong>na</strong><strong>to</strong>miast końcowym v n . Elementy w zbiorze<br />
nie mogą się powtarzać za wyjątkiem ostatniego i pierwszego elementu. Gdy<br />
v 1 = v n , drogę <strong>na</strong>zywamy cyklem. Każda krawędź w drodze musi być incydent<strong>na</strong><br />
do <strong>na</strong>stępujących po sobie wierzchołków.<br />
Definicja. Graf <strong>na</strong>zywamy spójnym, gdy pomiędzy dwoma dowolnymi wierzchołkami<br />
w grafie istnieje droga.<br />
A.1 Spójność krawędziowa i wierzchołkowa<br />
Pod terminem spójności krawędziowej λ(G) ukrywa się minimal<strong>na</strong> liczba krawędzi<br />
jaką <strong>na</strong>leży usunąć z grafu, by graf przestał być spójny. Odpowiednio przez<br />
spójność wierzchołkową κ(G) rozumiemy minimalną ilość wierzchołków jaką<br />
<strong>na</strong>leży usunąć z grafu, żeby graf przestał być spójny. Operacja usunięcia wierzchołka<br />
pociąga za sobą usunięcie wszystkich krawędzi incydentnych do tego<br />
wierzchołka. Łatwo zauważyć, że istnieje związek między spójnością wierzchołkową,<br />
a krawędziową κ(G) ≤ λ(G). Jednocześnie spójność krawędziowa<br />
nie może przekroczyć λ(G) ≤ ⌊ ⌋<br />
2e<br />
n .<br />
Liczba dróg rozłącznych krawędziowo i wierzchołkowo związa<strong>na</strong> jest ze spójnością<br />
krawędziową grafu. Gdy rozpatrujemy liczbę dróg z wierzchołka u do v<br />
<strong>to</strong> możemy łatwo z<strong>na</strong>leźć oszacowania górne <strong>na</strong> tą war<strong>to</strong>ść. Oz<strong>na</strong>czając przez<br />
d(u) s<strong>to</strong>pień wierzchołka u oraz d(v) s<strong>to</strong>pień wierzchołka v, oszacowanie górne<br />
liczby dróg z wierzchołka u do v jest równe min{d(v),d(u)}<br />
A.2 Różne typy grafów<br />
Ustrukturalizowane i nieustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> organizują samoczynnie<br />
komunikację między węzłami sieci. Skalowalność obecnie s<strong>to</strong>sowanych<br />
systemów jest wynikiem doświadczeń oraz prób i błędów z rzeczywistymi,<br />
tes<strong>to</strong>wymi implementacjami. Dopiero od niedaw<strong>na</strong> zaczę<strong>to</strong> budować sieci <strong>peer</strong><strong>to</strong>-<strong>peer</strong><br />
używając takich strukturach grafowych, które zapewniają lepszą wydajność.<br />
Postanowiłem przedstawić w kilku punktach <strong>na</strong>jczęściej spotykane lub<br />
zalecane struktury grafowe w <strong>systemach</strong> <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>. Szczególnie obiecujące<br />
wydają się być grafy de Bruijn’a [LKRG03]. Grafy de Bruijn’a zostały zas<strong>to</strong>sowane<br />
do konstrukcji sieci Koorde [KK03].
A.2 Różne typy grafów 99<br />
Rysunek A.1: Grafy regularne o czterech wierzchołkach i s<strong>to</strong>pniu równym dwa,<br />
oraz sześciu wierzchołkach i s<strong>to</strong>pniu równym cztery.<br />
A.2.1<br />
Grafy regularne i grafy losowe<br />
Grafem regularnym <strong>na</strong>zywamy taki graf, w którym s<strong>to</strong>pień każdego wierzchołka<br />
w grafie ma taką samą war<strong>to</strong>ść ∀ v∈V d(v) =const. Spójność krawędziowa grafu<br />
r-regularnego jest rów<strong>na</strong> λ(G) =r. Grafy tego typu posiadają ważną właściwość<br />
ze względu <strong>na</strong> nieustrukturalizowane systemy <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong>, gdyż świetnie działają<br />
w nich pro<strong>to</strong>koły plotkarskie wspomniane w pierwszym rozdziale. Plotkowanie<br />
działa niezwykle dobrze w pewnej szczególnej podklasie grafów regularnych, a<br />
dokładniej w kra<strong>to</strong>wnicach (ang. lattices).<br />
Najbardziej z<strong>na</strong>nymi grafami losowymi są grafy Erdős’a. Konstrukcja tych<br />
grafów jest s<strong>to</strong>sunkowo prosta. Dla grafu o n wierzchołkach dane jest prawdopodobieństwo<br />
p istnienia krawędzi między dowolnymi dwoma wierzchołkami.<br />
Dla każdej pary wierzchołków jest losowane, czy są one do siebie incydentne.<br />
Średni s<strong>to</strong>pień wierzchołków zależy oczywiście od prawdopodobieństwa p oraz<br />
wielkości sieci i wynosi d = p(n − 1). Dla dużego n, rzędu kilku milionów,<br />
war<strong>to</strong>ść d będzie duża <strong>na</strong>wet dla p bliskiego jednej tysięcznej. W rzeczywistych<br />
sieciach prawdopodobieństwo istnienia krawędzi między węzłami nie jest jednolite.<br />
W sieciach up2p super węzły posiadają dużą liczbę połączeń, sięgającą<br />
<strong>na</strong>wet do kilkudziesięciu tysięcy. Węzły uczestniczące utrzymują prawie o rząd<br />
wielkości mniej połączeń niż super węzły.<br />
Ciekawą hybryda powstaje z połączenia grafów Erdős’a i grafów regularnych.<br />
Ustalamy, że p = 1 ,wtedyd =1oraz wybieramy pewną war<strong>to</strong>ść<br />
n−1<br />
r. Ustalamy, że s<strong>to</strong>pień każdego wierzchołka musi być przy<strong>na</strong>jmniej r, czyli<br />
d ′ = d · r. Oz<strong>na</strong>cza <strong>to</strong> mniej więcej tyle, że rozpatrując kolejny wierzchołek<br />
grafu, losujemy tak długo krawędzi do niego incydentne, aż s<strong>to</strong>pień wierzchołka<br />
nie wyniesie r. Każdego losowania istnienia krawędzi dokonujemy używając
100 Dodatek A. Elementy teorii grafów<br />
Rysunek A.2: Losowe grafy Erdős’a o dziesięciu wierzchołkach i prawdopodobieństwu<br />
istnienia krawędzi p =0.5, 0.3.<br />
prawdopodobieństwa p równego 1<br />
n−1 .<br />
A.2.2<br />
Grafy Butterfly<br />
Sieć motyla (ang. butterfly)od wymiarach, jest grafem samopodobnym, którego<br />
wierzchołki są oz<strong>na</strong>czone dwoma war<strong>to</strong>ściami (w, i), w jest ciągiem bi<strong>na</strong>rnym<br />
o długości d, ai jest liczbą całkowitą od 0 do d. Wierzchołek (w, i) połączony<br />
jest z wierzchołkiem (w ′ ,i+1)wtedy, gdy w i w ′ jest zgodne przedrostkiem<br />
za wyjątkiem, co <strong>na</strong>jwyżej i +1 bitów. Sieć motyla ma (d +1)2 d wierzchołków<br />
i d2 d+1 krawędzi. Na rysunku A.3 pokazano trzy sieci typu motyla, dla<br />
wymiaru d = {1, 2, 3}. Dla wymiaru równego d = 1 wierzchołki oz<strong>na</strong>kowane<br />
są <strong>na</strong>stępująco: (0, 0), (0, 1), (1, 0), (1, 1). Zasadniczą zaletą sieci motyla<br />
jest s<strong>to</strong>sunkowo prosta <strong>na</strong>wigacja. Gdy komunikat wędruje w sieci <strong>to</strong> dopóki nie<br />
osiągnie wierzchołka, z którym będzie zgodny prefiksem, <strong>to</strong> s<strong>to</strong>suje się przesyłanie<br />
przez węzły o identyfika<strong>to</strong>rach <strong>na</strong>jbliższych adresa<strong>to</strong>wi. Algorytm trasowania<br />
przedrostkowego Plax<strong>to</strong><strong>na</strong> s<strong>to</strong>suje się, gdy komunikat zacznie być zgodny co do<br />
początkowej części adresu z adresem węzła pośredniczącego.<br />
A.2.3<br />
Grafy de Bruijn’a<br />
Grafy de Bruijn’a są digrafami z oz<strong>na</strong>czonymi wierzchołkami. Grafy tego typu<br />
posiadają dwa parametry: m - liczbę z<strong>na</strong>ków w alfabecie M użytym do utworzenia<br />
tworzenia etykiety oraz wymiar n. Etykieta każdego wierzchołka jest<br />
długości n i składa się ze z<strong>na</strong>ków w M. Na rysunku A.4 pokazano grafy de<br />
Bruijn’a dla m =2, czyli np. dla 0 i 1 i n =3oraz n =4.Dlan =3graf ma<br />
8 wierzchołków, czyli {000, 001, 010, 011, 100, 101, 110, 111}. Dowolny wierz-
A.2 Różne typy grafów 101<br />
Rysunek A.3: Grafy butterfly dla n =1, 2, 3.<br />
Rysunek A.4: Grafy de Bruijn’a dla m =2oraz n =3i n =4.
102 Dodatek A. Elementy teorii grafów<br />
chołek jest incydentny do innego wierzchołka wtedy i tylko wtedy, gdy jakaś<br />
część etykiety obu wierzchołków zachodzi <strong>na</strong> siebie sufiksem lub prefiksem.<br />
Na przykład wierzchołek 000 jest incydentny do wierzchołków: 010, 001, 011.<br />
Szczególnie ciekawe jest, jak odbywa się wyszukiwanie drogi w takim grafie.<br />
Załóżmy, że interesuje <strong>na</strong>s droga z wierzchołka 000 do 111. Konstrukcja<br />
przebiega w <strong>na</strong>stępujący sposób. Wybieramy taki wierzchołek z wierzchołków<br />
incydentnych do 000, który jest <strong>na</strong>jbardziej zgodny z celem, czyli 011. Następny<br />
wierzchołek, który wybierzemy <strong>to</strong> cel, czyli 111. Całkowitą drogę możemy zapisać<br />
w postaci 000111, która jest rów<strong>na</strong> dwóm długościom adresu, co wyz<strong>na</strong>cza<br />
ilości kroków, jakie musi poko<strong>na</strong>ć komunikat, by dotrzeć do celu.
Dodatek B<br />
Uzgadnianie w asynchronicznym<br />
systemie<br />
Przedstawię szkic dowodu twierdzenia o niemożliwości uzgodnienia war<strong>to</strong>ści w<br />
całkowicie asynchronicznym systemie <strong>na</strong>wet wtedy, gdy w grupie jest tylko jeden<br />
niepoprawnie działający proces 1 . Pozwoli <strong>to</strong> zrozumieć dlaczego przedstawione<br />
algorytmy <strong>to</strong>lerancji bizantyjskich uszkodzeń używają synchroniczności, by osiągnąć<br />
zamierzony cel, jak również jest dobrym wprowadzeniem do zagadnienia<br />
praktycznego uzgadniania w <strong>systemach</strong> <strong>to</strong>lerujących uszkodzenia.<br />
B.1 Brak konsensusu i asynchroniczność<br />
Założenia i lematy. Niech P oz<strong>na</strong>cza pro<strong>to</strong>kół uzgadniania w asynchronicznym<br />
systemie z N procesami (N ≥ 2). Każdy z procesów p posiada dwa rejestry<br />
x p ,y p mogące przechowywać jedną z war<strong>to</strong>ści v ∈{b, 0, 1}, gdzie b oz<strong>na</strong>cza<br />
war<strong>to</strong>ść nieustaloną. Rejestr x p jest rejestrem początkowym, <strong>na</strong><strong>to</strong>miast y p jest<br />
rejestrem wyjściowym, który początkowo inicjowany jest war<strong>to</strong>ścią b. Gdy p<br />
ustala war<strong>to</strong>ść y p jego stan ustalany jest, jako zatwierdzony. Procesy działają<br />
w sposób deterministyczny zgodnie z pewną funkcją przejścia.<br />
Jako wiadomość, będziemy rozumieli parę (p, m), gdzie m ∈ M, gdzie M<br />
jest skończonym zbiorem elementów, a p oz<strong>na</strong>cza adresata wiadomości. Każdy<br />
z procesów posiada bufor wiadomości, który udostępnia dwie operacje:<br />
wyślij(p,m) umieszcza w buforze procesu p wiadomość m.<br />
odbierz(p) usuwa wiadomość (p, m) z bufora wołającego procesu lub zwraca φ<br />
jeżeli wiadomość nie z<strong>na</strong>jduje się w buforze. Wiadomość (p, m) uz<strong>na</strong>wa<strong>na</strong><br />
jest jako dostarczo<strong>na</strong> po wyko<strong>na</strong>niu operacji odbierz(p).<br />
1 Szczegóły zainteresowany czytelnik z<strong>na</strong>jdzie w artykule Fischera [FLP85]
104 Dodatek B. Uzgadnianie w asynchronicznym systemie<br />
Przez konfigurację C będziemy rozumieli stan wszystkich procesów wraz z<br />
zawar<strong>to</strong>ścią ich buforów. Konfiguracja początkowa jest ustalo<strong>na</strong> w sposób taki,<br />
iż każdy procesów jest w stanie początkowym, a bufory wiadomości są puste.<br />
Konfigurację początkową będziemy <strong>na</strong>zywali przyległą do innej konfiguracji, jeżeli<br />
różni się o<strong>na</strong> stanem wewnętrznym tylko jednego procesu p.<br />
Na krok wykonywany przez proces p składają się <strong>na</strong>stępujące czynności:<br />
wyko<strong>na</strong>nie operacji odbierz(p), zmiany stanu wewnętrznego, wysłaniu skończonego<br />
zbioru wiadomości do innych procesów. Wyko<strong>na</strong>nie kroku jest całkowicie<br />
uzależnione od e =(p, m), co będziemy <strong>na</strong>zywać zdarzeniem i jeżeli e przenosi<br />
konfigurację C do nowej konfiguracji, <strong>to</strong> nowa konfiguracja będzie oz<strong>na</strong>cza<strong>na</strong><br />
jako e(C).<br />
Przebiegiem σ będziemy określali skończony bądź nieskończony ciąg zdarzeń.<br />
Jeżeli σ będzie skończone <strong>to</strong> wynikową konfigurację dla C oz<strong>na</strong>czymy<br />
jako σ(C). Mówimy, że σ(C) jest osiągalne z C. C posiada war<strong>to</strong>ść decyzyjną<br />
v jeżeli y p = v dla jakiegoś p. P jest częściowo poprawny gdy spełnia<br />
<strong>na</strong>stępujące wymagania:<br />
1. Żad<strong>na</strong> z osiągalnych konfiguracji nie posiada więcej, jak jednej war<strong>to</strong>ści<br />
decyzyjnej.<br />
2. Dla każdej z war<strong>to</strong>ści v ∈{0, 1}, któraś z osiągalnych konfiguracji ustala<br />
war<strong>to</strong>ść v.<br />
P jest całkowicie poprawny niezależnie od jednego niepoprawnie działającego<br />
procesu jeżeli jest częściowo poprawny oraz każdy osiągalny przebieg posiada<br />
war<strong>to</strong>ść decyzyjną v. Możemy powiedzieć, że konfiguracja C jest dwuokreślo<strong>na</strong>,<br />
lubjednookreślo<strong>na</strong>, gdy istnieją dla niej przebiegi zarówno prowadzące,<br />
w pierwszym przypadku do decyzji {0, 1} lub tylko do 0 lub 1 w drugim przypadku.<br />
Konfigurację jednookreśloną rozróżniamy <strong>na</strong> 0-określoną i 1-określoną.<br />
Lemat 1 Załóżmy, że istnieje pew<strong>na</strong> konfiguracja C. Przebiegi σ 1 ,σ 2 prowadzą<br />
odpowiednio do wynikowych konfiguracji C 1 oraz C 2 . Jeżeli zbiory procesów<br />
biorących udział w przebiegach σ 1 ,σ 2 są rozłączne, <strong>to</strong> σ 1 może być zas<strong>to</strong>sowa<strong>na</strong><br />
do C 2 oraz σ 2 do C 1 i oba przebiegi będą prowadziły do pewnej konfiguracji<br />
C 3 .<br />
Dowód. Możemy podzielić N procesów <strong>na</strong> dwa rozłączne podzbiory A i B.<br />
Jeżeli σ 1 jest przebiegiem, który wiąże się ze zmianą stanu tylko dla procesów<br />
w A (brak komunikacji z B) orazσ 2 jest przebiegiem, który wiąże się ze zmianą<br />
stanu tylko dla procesów w B (brak komunikacji z A), <strong>to</strong> σ 1 (C A ) jest nową<br />
konfiguracją w A, aσ 2 (C B ) jest nową konfiguracją w B, po zas<strong>to</strong>sowaniu obu<br />
przebiegów. Ponieważ σ 1 ,σ 2 są rozłączne, <strong>to</strong> σ 1 (C A ) i σ 2 (C B ) też są rozłączne
B.1 Brak konsensusu i asynchroniczność 105<br />
oraz kolejność wyko<strong>na</strong>nia σ 1 i σ 2 jest bez z<strong>na</strong>czenia, zatem C 3 = σ 2 (σ 1 (C)) =<br />
σ 1 (σ 2 (C)).<br />
Lemat 2 P posiada zawsze dwuokreśloną konfigurację początkową.<br />
Dowód. Dowód przez zaprzeczenie. Załóżmy, że P ma 0-określoną lub 1-<br />
określoną konfigurację początkową. Jeżeli konfiguracja początkowa jest np. 0-<br />
określo<strong>na</strong>, <strong>to</strong> musi istnieć łańcuch konfiguracji początkowych prowadzących do<br />
C 1 . Niech C 0 oz<strong>na</strong>cza konfigurację początkową z łańcucha, która jest bezpośrednio<br />
przyległa do C 1 oraz p będzie procesem, w którym stan jest różny dla<br />
obu konfiguracji.<br />
Rozważmy decydujący przebieg σ z C 0 , w którym proces p nie wykonuje żadnego<br />
kroku, zatem σ może również zaistnieć dla C 1 . Jeżeli σ prowadzi do<br />
v =0<strong>to</strong> C 1 jest dwuokreślone, <strong>na</strong><strong>to</strong>miast jeżeli v =1,<strong>to</strong>C 0 jest dwuokreślone.<br />
Dlatego początkowa konfiguracja jest zawsze dwuokreślo<strong>na</strong>.<br />
Lemat 3 Niech C będzie dwuokreśloną konfiguracją w P oraz e =(p, m) będzie<br />
zdarzeniem istniejącym dla C. Niech C oz<strong>na</strong>cza zbiór konfiguracji osiągalnych<br />
z C bez zaistnienia e oraz D = e(C) ={e(E)|E ∈Ci e może zaistnieć w E},<br />
<strong>to</strong> D zawiera dwuokreśloną konfigurację.<br />
Dowód. Wiemy e może zajść w C, zatem rozpatrując definicję C oraz, że wiadomość<br />
może być opóźnia<strong>na</strong> dowolnie długo, <strong>to</strong> e może zaistnieć w dowolnym<br />
E ∈C. Załóżmy, że D nie zawiera dwuokreślonej konfiguracji. Udowodnimy,<br />
że tak nie jest.<br />
Oz<strong>na</strong>czymy E i , jako jednookreśloną konfigurację osiągalną z C, i ∈{0, 1}.<br />
Jeżeli E i ∈ C oraz F i = e(E i ) ∈ D. W innym przypadku e zaistniało by<br />
osiągnąć E i , więc istnieje F i ∈D, z którego E i jest osiągalne. Zawsze F i<br />
jest i-osiągalne, co wynika z założenia i zarówno F i jest osiągalne z E i ,jak<br />
i <strong>na</strong> odwrót. Zatem, gdy F i ∈Di D zawiera zarówno 1-osiągalną, jak i 0-<br />
osiągalną konfigurację. Nazwiemy dwie konfiguracje sąsiednimi jeżeli są one<br />
wzajemnie osiągalne tylko w jednym kroku. Istnieją takie sąsiednie konfiguracje<br />
C 1 ,C 2 ∈C,żeD i = e(C i ), i ∈{0, 1} i D i jest i-osiągalne, np. C 1 = e ′ (C 0 ),<br />
gdzie e ′ =(p ′ ,m ′ ). Do rozważenia konieczne są dwa przypadki:<br />
p ′ ≠ p Wtedy D 1 = e ′ (D 0 ), co jest niemożliwe zgodnie z lematem 1, gdyż konfiguracja<br />
<strong>na</strong>stępująca po 0-określonej musi być 0-określo<strong>na</strong>.
106 Dodatek B. Uzgadnianie w asynchronicznym systemie<br />
p ′ = p Rozważmy decydujący przebieg σ nie uwzględniający p z C 0 oraz niech<br />
A = σ(C 0 ). Z lematu 1 wynika, że σ może zaistnieć dla D i oraz prowadzi<br />
do i-określonej konfiguracji E i = σ(D i ),i ∈{0, 1}. Także z lematu<br />
1 wynika, e(A) =E 0 oraz e(e ′ (A)) = E 1 . Co za tym idzie, A jest dwuokreślone,<br />
co nie zgadza się z założeniem. Ostatecznie D musi zawierać<br />
dwuokreśloną konfigurację.<br />
Powyższe rozważania prowadzą do wniosku, że każdy decydujący przebieg<br />
rozpoczy<strong>na</strong>jący się dwuokreśloną konfiguracją przechodzi do jednookreślonej<br />
konfiguracji w jakimś kroku. Ten krok determinuje przyszłą war<strong>to</strong>ść decyzyjną.<br />
W całkowicie asynchronicznym pro<strong>to</strong>kole uzgadniania gdy jakikolwiek z procesów<br />
jest uszkodzony, moż<strong>na</strong> unikać takiego kroku, który powoduje przejście<br />
z dwuokreślonej konfiguracji do jednookreślonej. Używając udowodnionych lematów<br />
moż<strong>na</strong> pokazać, że <strong>na</strong>stępujące twierdzenie jest prawdziwe.<br />
Twierdzenie 5 Nie istnieje taki pro<strong>to</strong>kół asynchronicznego uzgadniania P, który<br />
byłby całkowicie poprawny, gdy chociaż jeden proces działa błędnie.<br />
Dowód. Przebieg, który nie prowadzi do uzgodnienia decyzji (war<strong>to</strong>ści) konstruowany<br />
jest w fazach. Utrzymywa<strong>na</strong> jest kolejka procesów początkowo nieuporządkowa<strong>na</strong>.<br />
Bufor wiadomości uporządkowany jest zgodnie z czasem ich<br />
<strong>na</strong>dania, w porządku od <strong>na</strong>jstarszej wiadomości do <strong>na</strong>jmłodszej. Każda faza<br />
składa się z pewnej liczby kroków. Faza przebiega począwszy od pierwszego<br />
procesu w kolejce procesów, którego bufor wiadomości nie jest pusty <strong>na</strong> początku<br />
fazy, odbiera on <strong>na</strong>jstarszą wiadomość i jest ustawiany <strong>na</strong> koniec kolejki.<br />
W ten sposób, żaden z procesów nie jest zagłodzony, wykonuje wszystkie kroki<br />
i odbiera wszelkie wysłane do niego wiadomości.<br />
Niech C 0 jest dwuokreśloną konfiguracją początkową, której istnienie gwarantuje<br />
lemat 2. Załóżmy, że proces p jest <strong>na</strong> początku kolejki procesów, a m<br />
jest <strong>na</strong>jstarszą wiadomością wysłaną do p, a w innym przypadku φ. Zdarzenie<br />
e =(p, m) jest ostatnim zdarzeniem przeprowadzającym konfigurację C do C ′ ,<br />
gdzie C ′ jest dwuokreślone co gwarantuje lemat 3. Ta sekwencja kroków zakańcza<br />
fazę.<br />
Każda faza zakańcza się dwuokreśloną konfiguracją, co prowadzi do nieskończonego<br />
przebiegu, gdzie decyzja nigdy nie zostaje podjęta, <strong>to</strong> pociąga za sobą,<br />
że P nie jest całkowicie poprawne.<br />
Zrozumienie tego dowodu daje świadomość, że nie ma pro<strong>to</strong>kołu, który pozwalałby<br />
podjąć decyzję przez grupę procesów, jeżeli któryś z nich nie działa
B.2 Uzgadnianie z częściowym zachowaniem poprawności 107<br />
poprawnie, chociaż może odpowiadać <strong>na</strong> otrzymane wiadomości. Musi istnieć<br />
mechanizm, gdzie pozostałe procesy są w stanie ustalić, który z procesów zawiódł<br />
i wykluczyć go z uzgadniania. Twierdzenie 1 jest is<strong>to</strong>tne z praktycznego<br />
punktu widzenia, gdyż wskazuje, że s<strong>to</strong>sowalne pro<strong>to</strong>koły muszą zakładać synchronizację<br />
między procesami w celu zapewnienia częściowej poprawności.<br />
B.2 Uzgadnianie z częściowym zachowaniem poprawności<br />
Rozpatrujemy system wprowadzony w poprzednim punkcie. Pokażemy pro<strong>to</strong>kół<br />
działający dwufazowo, który potwierdza poprawność <strong>na</strong>stępującego twierdzenia.<br />
Twierdzenie 6 Istnieje częściowo poprawny pro<strong>to</strong>kół uzgadniania, w którym<br />
wszystkie poprawnie działające procesy podejmą decyzję, jeżeli tylko stanowią<br />
większość i podczas uzgadniania wszystkie, te procesy pozostaną sprawne.<br />
Szkic dowodu. Każdy proces konstruuje skierowany graf G, gdzie węzłami są<br />
inne procesy, rozsyła do wszystkich procesów wiadomość ze swoim numerem i<br />
czeka <strong>na</strong> L − 1 odpowiedzi <strong>na</strong> wiadomość od innych procesów, L = ⌈ ⌉<br />
(N+1)<br />
2 . G<br />
ma gałąź od i do j jeżeli j odbierze wiadomość. G jest s<strong>to</strong>pnia L − 1.<br />
Druga faza. Procesy konstruują graf G + , tak, że każdy proces k po zakończeniu<br />
fazy z<strong>na</strong> wszystkie krawędzie (j, k) incydentne do k w G + ,jakrównież<br />
początkowe war<strong>to</strong>ści dla j. Konstrukcja G + przebiega w ten sposób, że każdy<br />
proces rozgłasza numery L − 1 procesów, od których otrzymało komunikat w<br />
fazie pierwszej, <strong>na</strong>stępnie czeka <strong>na</strong> odpowiedzi od każdego poprzednika w G z<br />
fazy pierwszej. W ten sposób k wie o L−1 sąsiadach, jak również o wszystkich<br />
węzłach, dla których on jest sąsiadem. Zatem każdy z procesów z<strong>na</strong> początkową<br />
klikę w G + o war<strong>to</strong>ści przy<strong>na</strong>jmniej L. Następnie każdy proces podejmuje<br />
decyzję <strong>na</strong> podstawie odebranych war<strong>to</strong>ści początkowych od innych procesów.<br />
Ten pro<strong>to</strong>kół ma bardzo ważną właściwość, a mianowicie wystarczy jedynie,<br />
⌈ <strong>to</strong> żeby⌉ większość procesów była spraw<strong>na</strong>, by uzgodnienie doszło do skutku<br />
(N+1)<br />
2 . Gdyby uzgodnienie nie doszło do skutku, bo jakiś z poprawnych procesów<br />
odmówiłby uczestniczenia w pro<strong>to</strong>kole, <strong>to</strong> konieczne byłoby rozpoczęcie<br />
uzgadniania od początku wykluczając ten proces. Opisany pro<strong>to</strong>kół do złudzenia<br />
przypomi<strong>na</strong> ten, który s<strong>to</strong>sowano do rozwiązania problemu bizanyjskich generałów,<br />
z tym wyjątkiem, że tu, każdy z uczestników uzgadnia jedną war<strong>to</strong>ść dla<br />
całej grupy.
Bibliografia<br />
[ADS02]<br />
[CC]<br />
J. Aspnes, Z. Diamadi, and G. Shah. Fault-<strong>to</strong>lerant routing in <strong>peer</strong><strong>to</strong>-<strong>peer</strong><br />
systems. In PODC ’02: Proceedings of the twenty-first<br />
annual symposium on Principles of distributed computing, pages<br />
223–232, New York, NY, USA, 2002. ACM Press.<br />
N. Christin and J. Chuang. A cost-based a<strong>na</strong>lysis of overlay routing<br />
geometries. In Proceedings of IEEE INFOCOM’05.<br />
[CDG + 02] Miguel Castro, Peter Druschel, Ayalvadi Ganesh, An<strong>to</strong>ny Rowstron,<br />
and Dan S. Wallach. Secure routing for structured <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
overlay networks. SIGOPS Oper. Syst. Rev., 36(SI):299–314, 2002.<br />
[CDKR02] Miguel Castro, Peter Druschel, Anne-Marie Kermarrec, and An<strong>to</strong>ny<br />
Rowstron. Scribe: A large-scale and decentralized application-level<br />
multicast infrastructure. IEEE Jour<strong>na</strong>l on Selected Areas in Communication<br />
(JSAC), 20(8), oct 2002.<br />
[CKPS01]<br />
[CKS00]<br />
Christian Cachin, Klaus Kursawe, Frank Petzold, and Vic<strong>to</strong>r Shoup.<br />
Secure and efficient asynchronous broadcast pro<strong>to</strong>cols. In CRYPTO<br />
’01: Proceedings of the 21st Annual Inter<strong>na</strong>tio<strong>na</strong>l Cryp<strong>to</strong>logy Conference<br />
on Advances in Cryp<strong>to</strong>logy, pages 524–541. Springer-Verlag,<br />
2001.<br />
Christian Cachin, Klaus Kursawe, and Vic<strong>to</strong>r Shoup. Random oracles<br />
in constantipole: practical asynchronous byzantine agreement<br />
using cryp<strong>to</strong>graphy (extended abstract). In PODC ’00: Proceedings<br />
of the nineteenth annual ACM symposium on Principles of distributed<br />
computing, pages 123–132. ACM Press, 2000.<br />
[CL99a] M. Castro and B. Liskov. A correctness proof for a practical<br />
byzantine-fault-<strong>to</strong>lerant replication algorithm. Technical report,<br />
1999.
110 BIBLIOGRAFIA<br />
[CL99b]<br />
[CL99c]<br />
Miguel Castro and Barbara Liskov. Authenticated byzantine fault<br />
<strong>to</strong>lerance without public-key cryp<strong>to</strong>graphy. Technical Memo MIT-<br />
LCS-TM-589, MIT, June 1999.<br />
Miguel Castro and Barbara Liskov. Practical byzantine fault <strong>to</strong>lerance.<br />
In OSDI ’99: Proceedings of the third symposium on Operating<br />
systems design and implementation, pages 173–186. USENIX<br />
Association, 1999.<br />
[CL00] Miguel Castro and Barbara Liskov. Proactive recovery in a<br />
byzantine-fault-<strong>to</strong>lerant system. In Fourth Symposium on Operating<br />
Systems Design and Implementation (OSDI), San Diego, USA,<br />
Oc<strong>to</strong>ber 2000.<br />
[CMM02]<br />
[Coh03]<br />
[CRB01]<br />
Russ Cox, Athicha Muthitacharoen, and Robert Morris. Serving dns<br />
using chord. In Proceedings of the 1st Inter<strong>na</strong>tio<strong>na</strong>l Workshop on<br />
Peer-<strong>to</strong>-Peer Systems (IPTPS), Cambridge, MA, March 2002.<br />
Bram Cohen. Incentives Build Robustness in BitTorrent. In Workshop<br />
on Economics of Peer-<strong>to</strong>-Peer Systems, Berkeley,CA,USA,<br />
June 2003.<br />
R. Chandra, V. Ramasubramanian, and K. Birman. Anonymous gossip:<br />
Improving multicast reliability in mobile ad-hoc networks. In<br />
ICDCS ’01: Proceedings of the The 21st Inter<strong>na</strong>tio<strong>na</strong>l Conference<br />
on Distributed Computing Systems, page 275. IEEE Computer Society,<br />
2001.<br />
[CSWH00] Ian Clarke, Oskar Sandberg, Brandon Wiley, and Theodore W.<br />
Hong. Freenet: A distributed anonymous information s<strong>to</strong>rage and<br />
retrieval system. In Proceedings of Designing Privacy Enhancing<br />
Technologies: Workshop on Design Issues in Anonymity and Unobservability,<br />
pages 46–66, July 2000.<br />
[CWC]<br />
N. Christin, A. Weigend, and J. Chuang. Content availability, pollution<br />
and poisoning in <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> file sharing networks. In Proceedings<br />
of ACM EC’05.<br />
[CY01] R. Chen and W. Yeager. Poblano - a distributed trust model for<br />
<strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> networks, 2001.<br />
[DMS04]<br />
R. Dingledine, N. Mathewson, and P. Syverson. Tor: The secondgeneration<br />
onion router, 2004.<br />
[Dou02] J. Douceur. The sybil attack, 2002.
BIBLIOGRAFIA 111<br />
[DZDS03]<br />
[FLP85]<br />
[FM02]<br />
F. Dabek, B. Zhao, P. Druschel, and I. S<strong>to</strong>ica. Towards a common<br />
api for structured <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> overlays, 2003.<br />
Michael J. Fischer, Nancy A. Lynch, and Michael S. Paterson. Impossibility<br />
of distributed consensus with one faulty process. J. ACM,<br />
32(2):374–382, 1985.<br />
Michael J. Freedman and Robert Morris. Tarzan: A <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
anonymizing network layer. In Proceedings of the 9th ACM Conference<br />
on Computer and Communications Security (CCS-9), Washing<strong>to</strong>n,<br />
D.C., November 2002.<br />
[Gon99] Li Gong. Inside Java 2 platform security architecture, API design,<br />
and implementation. Addison-Wesley Longman Publishing<br />
Co., Inc., Bos<strong>to</strong>n, MA, USA, 1999.<br />
[HKM + 87] J. Howard, M. Kazar, S. Menees, D. Nichols, M. Satya<strong>na</strong>raya<strong>na</strong>n,<br />
Robert N. Sidebotham, and M. West. Scale and performance in a<br />
distributed file system. In SOSP ’87: Proceedings of the eleventh<br />
ACM Symposium on Operating systems principles, pages 1–2, New<br />
York, NY, USA, 1987. ACM Press.<br />
[KBC + 00]<br />
[KK03]<br />
[KMR02]<br />
[KRT03]<br />
John Kubia<strong>to</strong>wicz, David Bindel, Yan Chen, Patrick Ea<strong>to</strong>n, Dennis<br />
Geels, Ramakrish<strong>na</strong> Gummadi, Sean Rhea, Hakim Weatherspoon,<br />
Westly Weimer, Chris<strong>to</strong>pher Wells, and Ben Zhao. Oceans<strong>to</strong>re: An<br />
architecture for global-scale persistent s<strong>to</strong>rage. In Proceedings of<br />
ACM ASPLOS. ACM, November 2000.<br />
M. Frans Kaashoek and David R. Karger. Koorde: A simple degreeoptimal<br />
distributed hash table. In Proceedings of the 2nd Inter<strong>na</strong>tio<strong>na</strong>l<br />
Workshop on Peer-<strong>to</strong>-Peer Systems (IPTPS ’03), 2003.<br />
A. Keromytis, V. Misra, and D. Rubenstein. Sos: Secure overlay<br />
services, 2002.<br />
J. Kangasharju, K. Ross, and D. Turner. Secure and resilient <strong>peer</strong><strong>to</strong>-<strong>peer</strong><br />
e-mail: Design and implementation, 2003.<br />
[LKRG03] D. Loguinov, A. Kumar, V. Rai, and S. Ganesh. Graph-theoretic<br />
a<strong>na</strong>lysis of structured <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> systems; routing distances and<br />
fault resilience. In In Proceedings of the ACM SIGCOMM ’03 Conference,<br />
Karlsruhe, Germany, August 2003., 2003.
112 BIBLIOGRAFIA<br />
[LNBK02] D. Liben-Nowell, H. Balakrish<strong>na</strong>n, and D. Karger. A<strong>na</strong>lysis of the<br />
evolution of <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> systems. In In Proceedings of the Twenty-<br />
First Annual Symposium on Principles of Distributed Computing.,<br />
pages 233–242. ACM Press, 2002., 2002.<br />
[MM02]<br />
[MVO96]<br />
[PRR97]<br />
P. Maymounkov and D. Mazieres. Kademlia: A <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> information<br />
system based on the xor metric, 2002.<br />
Alfred J. Menezes, Scott A. Vans<strong>to</strong>ne, and Paul C. Van Oorschot.<br />
Handbook of Applied Cryp<strong>to</strong>graphy. CRC Press, Inc., 1996.<br />
C. Greg Plax<strong>to</strong>n, Rajmohan Rajaraman, and Andrea W. Richa. Accessing<br />
nearby copies of replicated objects in a distributed environment.<br />
In ACM Symposium on Parallel Algorithms and Architectures,<br />
pages 311–320, 1997.<br />
[RD01a] An<strong>to</strong>ny Rowstron and Peter Druschel. S<strong>to</strong>rage ma<strong>na</strong>gement and<br />
caching in PAST, a large-scale, persistent <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> s<strong>to</strong>rage utility.<br />
In 18th ACM Symposium on Operating Systems Principles<br />
(SOSP’01), pages 188–201, oct 2001.<br />
[RD01b]<br />
[REG + 03]<br />
[RFH + 00]<br />
[RSA77]<br />
[SGR97]<br />
An<strong>to</strong>ny I. T. Rowstron and Peter Druschel. Pastry: Scalable, decentralized<br />
object location, and routing for large-scale <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong><br />
systems. In Middleware 2001: Proceedings of the IFIP/ACM Inter<strong>na</strong>tio<strong>na</strong>l<br />
Conference on Distributed Systems Platforms Heidelberg,<br />
pages 329–350. Springer-Verlag, 2001.<br />
S. Rhea, P. Ea<strong>to</strong>n, D. Geels, H. Weatherspoon, B. Zhao, and J. Kubia<strong>to</strong>wicz.<br />
Pond: The oceans<strong>to</strong>re pro<strong>to</strong>type. In Proceedings of the<br />
Conference on File and S<strong>to</strong>rage Technologies. USENIX, 2003.<br />
Sylvia Rat<strong>na</strong>samy, Paul Francis, Mark Handley, Richard Karp, and<br />
Scott Shenker. A scalable content addressable network. Technical<br />
Report TR-00-010, Berkeley, CA, 2000.<br />
R. L. Rivest, A. Shamir, and L. M. Adelman. A method for obtaining<br />
digital sig<strong>na</strong>tures and public-key cryp<strong>to</strong>systems. Technical Report<br />
MIT/LCS/TM-82, 1977.<br />
P F Syverson, D M Goldschlag, and M G Reed. Anonymous connections<br />
and onion routing. In IEEE Symposium on Security and<br />
Privacy, pages 44–54, Oakland, California, 4–7 1997.<br />
[Sha79] Adi Shamir. How <strong>to</strong> share a secret. Commun. ACM, 22(11):612–613,<br />
1979.
BIBLIOGRAFIA 113<br />
[Sho00]<br />
Vic<strong>to</strong>r Shoup. Practical threshold sig<strong>na</strong>tures. Lecture Notes in Computer<br />
Science, 1807:207, 2000.<br />
[SM02] Emil Sit and Robert Morris. Security considerations for <strong>peer</strong>-<strong>to</strong><strong>peer</strong><br />
distributed hash tables. In IPTPS ’01: Revised Papers from<br />
the First Inter<strong>na</strong>tio<strong>na</strong>l Workshop on Peer-<strong>to</strong>-Peer Systems, pages<br />
261–269. Springer-Verlag, 2002.<br />
[SMK + 01] Ion S<strong>to</strong>ica, Robert Morris, David Karger, Frans Kaashoek, and Hari<br />
Balakrish<strong>na</strong>n. Chord: A scalable Peer-To-Peer lookup service for<br />
internet applications. In Proceedings of the 2001 ACM SIGCOMM<br />
Conference, pages 149–160, 2001.<br />
[Ste99]<br />
W. Richard Stevens. UNIX network programming, volume 1,2 (2nd<br />
ed.). Prentice Hall PTR, 1999.<br />
[Tan95] Andrew S. Tanenbaum. Distributed operating systems. Prentice-<br />
Hall, Inc., Upper Saddle River, NJ, USA, 1995.<br />
[TS01]<br />
[ZHS + 03]<br />
[ZvRM02]<br />
Andrew S. Tanenbaum and Maarten Van Steen. Distributed Systems:<br />
Principles and Paradigms. Prentice Hall PTR, 2001.<br />
Ben Y. Zhao, Ling Huang, Jeremy Stribling, Sean C. Rhea, Anthony<br />
D Joseph, and John D. Kubia<strong>to</strong>wicz. Tapestry: A global-scale<br />
overlay for rapid service deployment. IEEE Jour<strong>na</strong>l on Selected<br />
Areas in Communications, 2003. Special Issue on Service Overlay<br />
Networks, <strong>to</strong> appear.<br />
Lidong Zhou, Robbert van Renesse, and Michael Marsh. Implementing<br />
ipv6 as a <strong>peer</strong>-<strong>to</strong>-<strong>peer</strong> overlay network. In SRDS ’02: Proceedings<br />
of the 21st IEEE Symposium on Reliable Distributed Systems<br />
(SRDS’02), page 347, Washing<strong>to</strong>n, DC, USA, 2002. IEEE Computer<br />
Society.