From 1d6d4053fd44faadfb22f9de033c2dfa583026c8 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Fri, 17 Sep 2021 14:44:05 +0300 Subject: [PATCH] chore: tidy up refs --- bibliography/references.bib | 87 +++++++++--------- .../2.3.merkle-trees.tex | 4 +- .../2.4.p2p-networks.tex | 2 +- .../2.5.blockchain.tex | 4 +- .../2.theoretical-background/2.6.ethereum.tex | 8 +- .../2.theoretical-background/2.7.ipfs.tex | 6 +- .../2.theoretical-background/2.8.orbit-db.tex | 4 +- thesis.pdf | Bin 979805 -> 979793 bytes 8 files changed, 56 insertions(+), 59 deletions(-) diff --git a/bibliography/references.bib b/bibliography/references.bib index b822183..04c64cd 100644 --- a/bibliography/references.bib +++ b/bibliography/references.bib @@ -1,10 +1,28 @@ -% examples... for more check out this: -% https://www.overleaf.com/learn/latex/bibliography_management_with_bibtex +% See also: https://www.overleaf.com/learn/latex/bibliography_management_with_bibtex -% proposed label naming convention: "chapter.subchapter-descriptive_name" -% for example: "2.2.2-why-gpg-is-awesome" +@online{2.3-merkle-tree, + author = {Wikipedia}, + title = {Merkle tree}, + url = {https://en.wikipedia.org/wiki/Merkle_tree} +} + +@online{2.3-merkle-proofs-explained, + author = {Belavadi Prahalad}, + title = {Merkle proofs Explained.}, + date = {2018-01-07}, + url = {https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5} +} + +@inproceedings{2.4-p2p-networking, + author={Schollmeier, R.}, + booktitle={Proceedings First International Conference on Peer-to-Peer Computing}, + title={A Definition of Peer-to-Peer Networking for the Classification of Peer-to-Peer Architectures and Applications}, + year={2001}, + pages={101-102}, + doi={10.1109/P2P.2001.990434} +} -@article{bitcoin, +@article{2.5-bitcoin, author = {Nakamoto, Satoshi}, year = {2009}, month = {03}, @@ -12,13 +30,13 @@ journal = {Cryptography Mailing list at https://metzdowd.com} } -@misc{blockchain, - author = "{Wikipedia}", - title = "Blockchain", - url = "https://en.wikipedia.org/wiki/Blockchain" +@misc{2.5-blockchain, + author = {Wikipedia}, + title = {Blockchain}, + url = {https://en.wikipedia.org/wiki/Blockchain} } -@online{ethereum-whitepaper, +@online{2.6-ethereum-whitepaper, author = {Vitalik Buterin}, title = {Ethereum Whitepaper}, date = {2013}, @@ -26,7 +44,7 @@ url = {https://ethereum.org/en/whitepaper} } -@article{ethereum-smart-contracts, +@article{2.6-ethereum-smart-contracts, author = {Savelyev, Alexander}, year = {2017}, month = {04}, @@ -37,7 +55,7 @@ doi = {10.1080/13600834.2017.1301036} } -@book{ethereum-mastering, +@book{2.6-ethereum-mastering, author = {Andreas M Antonopoulos, Gavin Wood}, title = {Mastering Ethereum: Building Smart Contracts and DApps}, date = {2018}, @@ -46,50 +64,29 @@ OPTurl = {https://cypherpunks-core.github.io/ethereumbook/}, } -@online{merkle-tree, - author = "Wikipedia", - title = "Merkle tree", - url = "https://en.wikipedia.org/wiki/Merkle_tree" +@misc{2.7-ipfs, + title = {IPFS}, + url = {https://ipfs.io/} } -@online{merkle-proofs-explained, - author = "Belavadi Prahalad", - title = "Merkle proofs Explained.", - date = "2018-01-07", - url = "https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5" +@misc{2.7-ipfs-docs, + title = {IPFS documentation}, + url = {https://docs.ipfs.io/} } -@misc{merkle-dags-proto-school, - author = "ProtoSchool", - title = "Merkle DAGs: Structuring Data for the Distributed Web", - url = "https://proto.school/merkle-dags/" +@misc{2.7-merkle-dags-proto-school, + author = {ProtoSchool}, + title = {Merkle DAGs: Structuring Data for the Distributed Web}, + url = {https://proto.school/merkle-dags/} } -@misc{ipfs, - title = "IPFS", - url = "https://ipfs.io/" -} - -@misc{ipfs-docs, - title = "IPFS documentation", - url = "https://docs.ipfs.io/" -} - -@misc{orbitdb, +@misc{2.8-orbitdb, title = {OrbitDB}, url = {https://orbitdb.org} } -@misc{orbitdb-guide, +@misc{2.8-orbitdb-guide, title = {Getting Started with OrbitDB}, url = {https://github.com/orbitdb/orbit-db/blob/main/GUIDE.md} } -@inproceedings{p2p-networking, - author={Schollmeier, R.}, - booktitle={Proceedings First International Conference on Peer-to-Peer Computing}, - title={A Definition of Peer-to-Peer Networking for the Classification of Peer-to-Peer Architectures and Applications}, - year={2001}, - pages={101-102}, - doi={10.1109/P2P.2001.990434} -} diff --git a/chapters/2.theoretical-background/2.3.merkle-trees.tex b/chapters/2.theoretical-background/2.3.merkle-trees.tex index 4b31895..e7a8475 100644 --- a/chapters/2.theoretical-background/2.3.merkle-trees.tex +++ b/chapters/2.theoretical-background/2.3.merkle-trees.tex @@ -1,6 +1,6 @@ \section{Δένδρα Merkle} -Ένα δένδρο Merkle (Merkle tree ή hash tree) είναι μία δενδρική δομή δεδομένων, η οποία απαρτίζεται από φύλλα (leaf nodes), που περιέχουν hashes από blocks δεδομένων, και από άλλους κόμβους (non-leaf nodes), οι οποίοι περιέχουν τα hashes των θυγατρικών τους. Στην κορυφή του δένδρου βρίσκεται το λεγόμενο root hash\cite{merkle-tree}. +Ένα δένδρο Merkle (Merkle tree ή hash tree) είναι μία δενδρική δομή δεδομένων, η οποία απαρτίζεται από φύλλα (leaf nodes), που περιέχουν hashes από blocks δεδομένων, και από άλλους κόμβους (non-leaf nodes), οι οποίοι περιέχουν τα hashes των θυγατρικών τους. Στην κορυφή του δένδρου βρίσκεται το λεγόμενο root hash\cite{2.3-merkle-tree}. Η πιο συνηθισμένη υλοποίηση είναι το δυαδικό (binary) δένδρο Merkle, το οποίο περιλαμβάνει δύο θυγατρικούς κόμβους (child nodes) κάτω από κάθε γονικό non-leaf κόμβο, και είναι αυτό που αναλύεται στη συνέχεια. @@ -12,5 +12,5 @@ \begin{itemize} \item Να αποφανθούμε εάν κάποια δεδομένα ανήκουν στο δένδρο (με τον αριθμό των hashes που θα πρέπει να υπολογιστούν να είναι ανάλογος του λογαρίθμου του αριθμού των leaf nodes). \item Να αποδείξουμε συνοπτικά την εγκυρότητα ενός τμήματος κάποιου σετ δεδομένων, χωρίς να χρειαστεί να αποθηκεύσουμε ολόκληρο το σύνολο δεδομένων. - \item Να διασφαλίσουμε την εγκυρότητα ενός συγκεκριμένου συνόλου δεδομένων εντός ενός μεγαλύτερου σύνολου, χωρίς να χρειαστεί να αποκαλυφθεί το περιεχόμενο οποιουδήποτε εκ των δύο\cite{merkle-proofs-explained}. + \item Να διασφαλίσουμε την εγκυρότητα ενός συγκεκριμένου συνόλου δεδομένων εντός ενός μεγαλύτερου σύνολου, χωρίς να χρειαστεί να αποκαλυφθεί το περιεχόμενο οποιουδήποτε εκ των δύο\cite{2.3-merkle-proofs-explained}. \end{itemize} diff --git a/chapters/2.theoretical-background/2.4.p2p-networks.tex b/chapters/2.theoretical-background/2.4.p2p-networks.tex index 7a32df4..cb96cc0 100644 --- a/chapters/2.theoretical-background/2.4.p2p-networks.tex +++ b/chapters/2.theoretical-background/2.4.p2p-networks.tex @@ -1,6 +1,6 @@ \section{Δίκτυα Ομότιμων Κόμβων} -Τα δίκτυα ομότιμων κόμβων ή Peer-to-Peer (P2P) networks αποτελούν μία κατανεμημένη αρχιτεκτονική δικτύων, οι συμμετέχοντες (κόμβοι) της οποίας μοιράζονται ένα τμήμα των πόρων τους, με στόχο την παροχή κάποιας υπηρεσίας (π.χ. τον διαμοιρασμό περιεχομένου). Εν αντιθέσει με συγκεντρωτικά δίκτυα τύπου client/server, οι κόμβοι (nodes) έχουν απευθείας πρόσβαση στους πόρους, χωρίς τη διαμεσολάβηση ενδιάμεσων οντοτήτων. Οι συμμετέχοντες ενός τέτοιου δικτύου είναι, δηλαδή, ταυτόχρονα, τόσο πάροχοι, όσο και αιτούντες των πόρων και της παρεχόμενης υπηρεσίας.\cite{p2p-networking} +Τα δίκτυα ομότιμων κόμβων ή Peer-to-Peer (P2P) networks αποτελούν μία κατανεμημένη αρχιτεκτονική δικτύων, οι συμμετέχοντες (κόμβοι) της οποίας μοιράζονται ένα τμήμα των πόρων τους, με στόχο την παροχή κάποιας υπηρεσίας (π.χ. τον διαμοιρασμό περιεχομένου). Εν αντιθέσει με συγκεντρωτικά δίκτυα τύπου client/server, οι κόμβοι (nodes) έχουν απευθείας πρόσβαση στους πόρους, χωρίς τη διαμεσολάβηση ενδιάμεσων οντοτήτων. Οι συμμετέχοντες ενός τέτοιου δικτύου είναι, δηλαδή, ταυτόχρονα, τόσο πάροχοι, όσο και αιτούντες των πόρων και της παρεχόμενης υπηρεσίας.\cite{2.4-p2p-networking} Τα P2P networks μπορούν να χωριστούν σε δύο κατηγορίες: diff --git a/chapters/2.theoretical-background/2.5.blockchain.tex b/chapters/2.theoretical-background/2.5.blockchain.tex index 4a4d724..3ffe821 100644 --- a/chapters/2.theoretical-background/2.5.blockchain.tex +++ b/chapters/2.theoretical-background/2.5.blockchain.tex @@ -1,8 +1,8 @@ \section{Blockchain} -Το blockchain αποτελεί μία διανεμημένη δημόσια σειρά δεδομένων, που διατηρεί έναν αμετάβλητο ως προς το ιστορικό του κατάλογο (immutable ledger) ψηφιακών συναλλαγών (digital transactions) ενός αγαθού (asset), π.χ. ενός νομίσματος (token). Περιγράφηκε για πρώτη φορά το 2008 από ένα άτομο (ή μία ομάδα ανθρώπων) γνωστό ως Satoshi Nakamoto, αποτελώντας τη βάση του κρυπτονομίσματος (cryptocurrency) Bitcoin.\cite{bitcoin} +Το blockchain αποτελεί μία διανεμημένη δημόσια σειρά δεδομένων, που διατηρεί έναν αμετάβλητο ως προς το ιστορικό του κατάλογο (immutable ledger) ψηφιακών συναλλαγών (digital transactions) ενός αγαθού (asset), π.χ. ενός νομίσματος (token). Περιγράφηκε για πρώτη φορά το 2008 από ένα άτομο (ή μία ομάδα ανθρώπων) γνωστό ως Satoshi Nakamoto, αποτελώντας τη βάση του κρυπτονομίσματος (cryptocurrency) Bitcoin.\cite{2.5-bitcoin} -Δομικό στοιχείο του blockchain είναι το μπλοκ (block), το οποίο περιέχει μία ομάδα έγκυρων συναλλαγών που έχουν κατακερματιστεί και κωδικοποιηθεί σε ένα δένδρο Merkle, το hash του προηγούμενου μπλοκ και μερικά ακόμα μεταδεδομένα (π.χ. nonce, timestamp). Έτσι, κάθε νέο μπλοκ "δείχνει" στο προηγούμενό του μέσω του hash, επιβεβαιώνοντας την ακεραιότητά του, με τα διαδεχόμενα μπλοκ να σχηματίζουν τελικά μία αλυσίδα, μέχρι το αρχικό μπλοκ, το οποίο είναι γνωστό ως το μπλοκ γένεσης (genesis block).\cite{blockchain} +Δομικό στοιχείο του blockchain είναι το μπλοκ (block), το οποίο περιέχει μία ομάδα έγκυρων συναλλαγών που έχουν κατακερματιστεί και κωδικοποιηθεί σε ένα δένδρο Merkle, το hash του προηγούμενου μπλοκ και μερικά ακόμα μεταδεδομένα (π.χ. nonce, timestamp). Έτσι, κάθε νέο μπλοκ "δείχνει" στο προηγούμενό του μέσω του hash, επιβεβαιώνοντας την ακεραιότητά του, με τα διαδεχόμενα μπλοκ να σχηματίζουν τελικά μία αλυσίδα, μέχρι το αρχικό μπλοκ, το οποίο είναι γνωστό ως το μπλοκ γένεσης (genesis block).\cite{2.5-blockchain} %TODO: add image like https://cdn.hackernoon.com/hn-images/1*qYKsqQ6aV-DgFD0REfcnig.png or https://ethereum.org/static/6f7d50fd4fab9f8abb94b5e610ade7e4/bf8c1/ethereum-blocks.png --- add that this is simplified diff --git a/chapters/2.theoretical-background/2.6.ethereum.tex b/chapters/2.theoretical-background/2.6.ethereum.tex index aab3449..b046e70 100644 --- a/chapters/2.theoretical-background/2.6.ethereum.tex +++ b/chapters/2.theoretical-background/2.6.ethereum.tex @@ -6,12 +6,12 @@ \caption{Ethereum logo} \end{figure} -Το Ethereum είναι ένα δημόσιο blockchain ανοιχτού κώδικα με εγγενές κρυπτονόμισμα το Ether (ETH). Παρέχει μία προγραμματιστική πλατφόρμα με ενσωματωμένη μία Turing-complete γλώσσα προγραμματισμού, που μπορεί να χρησιμοποιηθεί για τη δημιουργία αποκεντρωμένων εφαρμογών (Decentralized Applications ή DApps) μέσω της χρήσης "έξυπνων συμβολαίων" (smart contracts).\cite{ethereum-whitepaper} +Το Ethereum είναι ένα δημόσιο blockchain ανοιχτού κώδικα με εγγενές κρυπτονόμισμα το Ether (ETH). Παρέχει μία προγραμματιστική πλατφόρμα με ενσωματωμένη μία Turing-complete γλώσσα προγραμματισμού, που μπορεί να χρησιμοποιηθεί για τη δημιουργία αποκεντρωμένων εφαρμογών (Decentralized Applications ή DApps) μέσω της χρήσης "έξυπνων συμβολαίων" (smart contracts).\cite{2.6-ethereum-whitepaper} \subsection{Smart Contracts \& DApps} Με απλά λόγια, τα smart contracts αποτελούν αυτόνομα κομμάτια κώδικα τα οποία είναι αποθηκευμένα στο blockchain και ενεργοποιούνται μέσω συναλλαγών. Μπορούν να διαβάζουν και να γράφουν δεδομένα επί του blockchain, κληρονομώντας ιδιότητες όπως τη διαφάνεια (transparency), την εγκυρότητα (validability) και την αμεταβλητότητα (immutability). -Ένα παράδειγμα της καθημερινότητας που μπορεί να παρομοιασθεί λειτουργικά με smart contract είναι ο αυτόματος πωλητής\cite{ethereum-smart-contracts}. Ένας αυτόματος πωλητής ορίζεται ως ένα αυτόνομο μηχάνημα που διανέμει αγαθά ή παρέχει υπηρεσίες όταν εισάγονται σε αυτόν κέρματα ή κάποια ηλεκτρονική πληρωμή. Οι αυτόματοι πωλητές είναι προγραμματισμένοι να εκτελούν συγκεκριμένους κανόνες που θα μπορούσαν να οριστούν σε ένα συμβόλαιο. +Ένα παράδειγμα της καθημερινότητας που μπορεί να παρομοιασθεί λειτουργικά με smart contract είναι ο αυτόματος πωλητής\cite{2.6-ethereum-smart-contracts}. Ένας αυτόματος πωλητής ορίζεται ως ένα αυτόνομο μηχάνημα που διανέμει αγαθά ή παρέχει υπηρεσίες όταν εισάγονται σε αυτόν κέρματα ή κάποια ηλεκτρονική πληρωμή. Οι αυτόματοι πωλητές είναι προγραμματισμένοι να εκτελούν συγκεκριμένους κανόνες που θα μπορούσαν να οριστούν σε ένα συμβόλαιο. Με όμοιο τρόπο, σε ένα smart contract μπορούν να κωδικοποιηθούν αυθαίρετες συναρτήσεις μετάβασης, επιτρέποντας τη δημιουργία ποικίλων αποκεντρωμένων εφαρμογών. Οι εφαρμογές αυτές μπορούν να χωριστούν σε τρεις κατηγορίες: \begin{itemize} @@ -19,7 +19,7 @@ \item Ημι-οικονομικές εφαρμογές, όπου εμπλέκονται χρήματα, αλλά η λειτουργία τους εμπεριέχει παράλληλα και μία αξιοσημείωτη μη νομισματική πλευρά. Ένα τέτοιο παράδειγμα είναι οι αυτόματες πληρωμές για λύσεις σε υπολογιστικά προβλήματα (βλ. Gitcoin). - \item Μη οικονομικές εφαρμογές, όπως η αποκεντρωμένη αποθήκευση δεδομένων, συστήματα ταυτότητας (identity) και φήμης (reputation), διαδικτυακές ψηφοφορίες και αποκεντρωμένη διακυβέρνηση. Οι τελευταίες εισάγουν και την έννοια των Αποκεντρωμένων Αυτόνομων Οργανώσεων (Decentralized Autonomous Organizations ή DAOs), οντοτήτων που ενεργούν αυτόνομα, χωρίς την ανάγκη διαμεσολάβησης κάποιας συγκεντρωτικής (centralized) αρχής.\cite{ethereum-whitepaper} + \item Μη οικονομικές εφαρμογές, όπως η αποκεντρωμένη αποθήκευση δεδομένων, συστήματα ταυτότητας (identity) και φήμης (reputation), διαδικτυακές ψηφοφορίες και αποκεντρωμένη διακυβέρνηση. Οι τελευταίες εισάγουν και την έννοια των Αποκεντρωμένων Αυτόνομων Οργανώσεων (Decentralized Autonomous Organizations ή DAOs), οντοτήτων που ενεργούν αυτόνομα, χωρίς την ανάγκη διαμεσολάβησης κάποιας συγκεντρωτικής (centralized) αρχής.\cite{2.6-ethereum-whitepaper} \end{itemize} \subsection{EVM} @@ -33,6 +33,6 @@ \item Ένας χώρος μόνιμης αποθήκευσης, που είναι μέρος του Ethereum state, επίσης αρχικά μηδενισμένος. \end{itemize} -Υπάρχει, επίσης, ένα σύνολο μεταβλητών περιβάλλοντος και δεδομένων, που είναι διαθέσιμα κατά την εκτέλεση.\cite{ethereum-mastering} +Υπάρχει, επίσης, ένα σύνολο μεταβλητών περιβάλλοντος και δεδομένων, που είναι διαθέσιμα κατά την εκτέλεση.\cite{2.6-ethereum-mastering} % TODO: Add account types, addressing, token types, fees,... diff --git a/chapters/2.theoretical-background/2.7.ipfs.tex b/chapters/2.theoretical-background/2.7.ipfs.tex index 578cbe7..630e3e0 100644 --- a/chapters/2.theoretical-background/2.7.ipfs.tex +++ b/chapters/2.theoretical-background/2.7.ipfs.tex @@ -6,8 +6,8 @@ \caption{IPFS logo} \end{figure} -Το IPFS (InterPlanetary File System) είναι \textit{ένα P2P πρωτόκολλο υπερμέσων, σχεδιασμένο για να διατηρήσει και να αυξήσει τη γνώση της ανθρωπότητας κάνοντας το διαδίκτυο αναβαθμίσιμο, ανθεκτικό και πιο ανοιχτό}.\cite{ipfs} -Πρακτικά πρόκειται για ένα κατανεμημένο σύστημα για αποθήκευση και πρόσβαση σε αρχεία, ιστότοπους, εφαρμογές και δεδομένα. Το περιεχόμενο είναι προσβάσιμο μέσω ενός δικτύου ομότιμων κόμβων που βρίσκονται οπουδήποτε στον κόσμο, οι οποίοι ενδέχεται να να αποθηκεύουν πληροφορία, να τη μεταφέρουν (relay nodes) ή και τα δύο.\cite{ipfs-docs} +Το IPFS (InterPlanetary File System) είναι \textit{ένα P2P πρωτόκολλο υπερμέσων, σχεδιασμένο για να διατηρήσει και να αυξήσει τη γνώση της ανθρωπότητας κάνοντας το διαδίκτυο αναβαθμίσιμο, ανθεκτικό και πιο ανοιχτό}.\cite{2.7-ipfs} +Πρακτικά πρόκειται για ένα κατανεμημένο σύστημα για αποθήκευση και πρόσβαση σε αρχεία, ιστότοπους, εφαρμογές και δεδομένα. Το περιεχόμενο είναι προσβάσιμο μέσω ενός δικτύου ομότιμων κόμβων που βρίσκονται οπουδήποτε στον κόσμο, οι οποίοι ενδέχεται να να αποθηκεύουν πληροφορία, να τη μεταφέρουν (relay nodes) ή και τα δύο.\cite{2.7-ipfs-docs} Ο τρόπος λειτουργίας του IPFS βασίζεται στα εξής: @@ -17,7 +17,7 @@ \begin{figure}[H] \centering \includegraphics[width=15cm]{merkle-dag.png} - \caption{Merkle DAG\cite{merkle-dags-proto-school}} + \caption{Merkle DAG\cite{2.7-merkle-dags-proto-school}} \end{figure} Στο παραπάνω Merkle DAG τα baf...i αποτελούν τα CID των αρχείων και των φακέλων. Το δένδρο δημιουργείται από κάτω προς τα πάνω, υπολογίζοντας κάθε φορά τα κατάλληλα hashes/CIDs. Σε περίπτωση που το περιεχόμενο ενός κόμβου αλλάξει, τότε αλλάζει τόσο το CID του, όσο και τα CIDs όλων των προγόνων του. \item \textbf{Ανακάλυψη περιεχομένου μέσω κατανεμημένων πινάκων κατακερματισμού (Distributed Hash Tables ή DHTs)}. Ο DHT είναι ένα κατανεμημένο σύστημα για την αντιστοίχιση κλειδιών σε τιμές. Στο IPFS αποτελεί το θεμελιώδες συστατικό του συστήματος δρομολόγησης περιεχομένου και λειτουργεί ως διασταύρωση μεταξύ καταλόγου και συστήματος πλοήγησης. Πρακτικά πρόκειται για ένα πίνακα που αποθηκεύει ποιος έχει ποια δεδομένα και, μέσω του οποίου, ο χρήστης βρίσκει τον peer που έχει αποθηκευμένο το επιθυμητό περιεχόμενο. diff --git a/chapters/2.theoretical-background/2.8.orbit-db.tex b/chapters/2.theoretical-background/2.8.orbit-db.tex index 97be2fe..d553bd2 100644 --- a/chapters/2.theoretical-background/2.8.orbit-db.tex +++ b/chapters/2.theoretical-background/2.8.orbit-db.tex @@ -6,7 +6,7 @@ \caption{OrbitDB logo} \end{figure} -Η OrbitDB είναι μία P2P βάση δεδομένων ανοιχτού κώδικα. Χρησιμοποιεί το IPFS για την αποθήκευση των δεδομένων και το IPFS Pubsub για τον αυτόματο συγχρονισμό των βάσεων δεδομένων μεταξύ των peers. Είναι μία τελικά συνεπής (eventually consistent) και χρησιμοποιεί CRDTs (Conflict-Free Replicated Data Types) για συγχωνεύσεις βάσεων δεδομένων χωρίς συγκρούσεις, πράγμα που την καθιστά εξαιρετική επιλογή για DApps και offline-first web applications.\cite{orbitdb} +Η OrbitDB είναι μία P2P βάση δεδομένων ανοιχτού κώδικα. Χρησιμοποιεί το IPFS για την αποθήκευση των δεδομένων και το IPFS Pubsub για τον αυτόματο συγχρονισμό των βάσεων δεδομένων μεταξύ των peers. Είναι μία τελικά συνεπής (eventually consistent) και χρησιμοποιεί CRDTs (Conflict-Free Replicated Data Types) για συγχωνεύσεις βάσεων δεδομένων χωρίς συγκρούσεις, πράγμα που την καθιστά εξαιρετική επιλογή για DApps και offline-first web applications.\cite{2.8-orbitdb} Κάποια Βασικά χαρακτηριστικά της είναι τα εξής: \begin{itemize} @@ -22,7 +22,7 @@ Όλα τα stores υλοποιούνται πάνω στο \texttt{ipfs-log}, μία αμετάβλητη, operation-based CRDT για κατανεμημένα συστήματα, ενώ υπάρχει και η δυνατότητα δημιουργίας προσαρμοσμένων stores ανάλογα με την περίπτωση. - \item \textbf{Address}: Κάθε βάση δεδομένων λαμβάνει κατά τη δημιουργία της μία διεύθυνση της μορφής: \texttt{/orbitdb/CID/DATABASE\_NAME}, όπου CID είναι το IPFS multihash του μανιφέστου της, ενώ το DATABASE\_NAME είναι το όνομα της βάσης\cite{orbitdb-guide}. Το μανιφέστο είναι ένα IPFS object που περιέχει πληροφορίες της βάσης όπως το όνομα, τον τύπο και έναν δείκτη στον ελεγκτή πρόσβασης (access controller). + \item \textbf{Address}: Κάθε βάση δεδομένων λαμβάνει κατά τη δημιουργία της μία διεύθυνση της μορφής: \texttt{/orbitdb/CID/DATABASE\_NAME}, όπου CID είναι το IPFS multihash του μανιφέστου της, ενώ το DATABASE\_NAME είναι το όνομα της βάσης\cite{2.8-orbitdb-guide}. Το μανιφέστο είναι ένα IPFS object που περιέχει πληροφορίες της βάσης όπως το όνομα, τον τύπο και έναν δείκτη στον ελεγκτή πρόσβασης (access controller). \item \textbf{Identity}: Κάθε φορά που προστίθεται μία εγγραφή στη βάση υπογράφεται από τον δημιουργό της, ο οποίος προσδιορίζεται από μία ταυτότητα (identity). Το Identity object, πέρα από τον προεπιλεγμένο τρόπο λειτουργίας, μπορεί να προσαρμοστεί έτσι ώστε να συνδέεται με κάποιο εξωτερικό αναγνωριστικό. Η μορφή του έχει ως εξής (βλ. και \url{https://github.com/orbitdb/orbit-db-identity-provider}): diff --git a/thesis.pdf b/thesis.pdf index 1cb47c6554c98eafa85be31c0e66efa92a3aaa17..d2a5a86f3b1341fd1c617570ea329dc2aa6dedf7 100644 GIT binary patch delta 15093 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