10.03.2015 Views

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 ...

SHOW MORE
SHOW LESS

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.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!