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

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

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!