diff --git a/Protocol.md b/Protocol.md deleted file mode 100644 index 857edc0f2605347e138ef9addd00d79504ed5ce2..0000000000000000000000000000000000000000 --- a/Protocol.md +++ /dev/null @@ -1,233 +0,0 @@ -# Protocol - -## Informal description - -**FYgg** is a **decentralised operating system** protocol managing permissioned **tokens** -that can represent programs, states, assets or even currency units. A token can have children an -defines how they can be **created**, **provided**, **updated** or **destroyed** in a specialized -**pure functionnal programming language**. The protocol *as is* is **usage-agnostic** and unable -to perform any task of it's own except running the *root token* main function, and its power comes -from the ability of tokens to program how them and their children can be used. These programs are -not meant to perform complex calculation, but only to verify the new state is valid. - -When created a token is assigned a **unique and definitive ID**, while it also have a **state ID** -changing each time the token is updated to avoid *replay attacks*. Children are stored in a -**Merkle tree** structure, the parent storing the **Merkle root** of the tree while the -**Merkle proof** of the children must be provided when it's used. Thanks to this it's possible to -discard any token while begin able to verify **state updates** (or **transformations**) if all used -tokens and their proofs are provided. - -**Transformations** (or *transforms* for short) describes changed in a group of tokens. It list -tokens which are used together and can store additionnal data (such as signatures) which can be used -to verify their validity. A token can be used in multiple transforms if multiple sub-groups of -tokens require different additionnal data. Each of these individual transforms can be invalid but as -a whole become valid. A transform stores a list of transforms it depends on (sub-groups transforms -or child token transforms). These dependencies make a **directed acyclic graph** which can be -used in token programs to verify rules. - -By default, many things are not verified automatically and are dangerous unless they are check -manually by token programs. By this construct it's possible to create really complex systems which -could not be created otherwise while allowing to make a globally secure tree. For exemple, it's -possible by default to create a token with a *subtree Merkle root* **without** providing nor -verifying its children. Most tokens will forbid this, but it can be used to import a large amount of -somehow trusted tokens into the tree. The main usage is cross-tree communication with trust coming -from an user-based oracle (detailed later in this document), allowing bandswitch and computation -sharding between multiple independent trees. - -## Formal description - -### Conventions - -All data is [big-endian], [aligned] in 2 bytes blocks and sizes are given in bytes unless otherwise -specified. - -*Cryptographic hashes* are done with the [SHA-256] algorithm unless otherwise specified. They are -stored as raw bytes arrays. - -Cryptographic keys and signatures are wrapped into an unified format to allow usage of multiple -cryptographic systems. - -| Size | Description -|:----:|:--- -| 2 | Cryptographic system code -| ... | Public key data / Signature data - -> The size of the public key depends of the cryptographic system used. - -For now, only [ed25519] public keys and signatures are supported with code `0x0000`. - -In this document all *keys* and *signatures* will use this format unless otherwise specified. - -[big-endian]: https://en.wikipedia.org/wiki/Endianness -[aligned]: https://en.wikipedia.org/wiki/Data_structure_alignment -[SHA-256]: https://en.wikipedia.org/wiki/SHA-2 -[ed25519]: https://en.wikipedia.org/wiki/EdDSA - -### Data structures - -#### Storage - -| Size | Description -|:----:|:--- -| 2 | Item 0 size -| 2 | Item 1 size -| 2 | Item 2 size -| | ... -| ... | Item 0 data -| ... | Item 1 data -| ... | Item 2 data -| | ... - -#### Token family - -| Size | Description -|:----:|:--- -| 2 | Script system version (allow to add new script systems via soft-forks, with unknown script systems always returning `true` ) -| 32 | Family creation script hash (complete script is provided alongside if needed) -| 32 | Family reading script hash (same) -| 32 | Family consumption script hash (same) - -#### Token - -| Size | Description -|:----:|:--- -| 32 | Token family hash -| 32 | Subtree root (filled with zeros if none) -| 32 | Primary bag input footprint -| 2 | Nonce -| 8 | Creation timestamp -| 2 | Storage size (in items) -| | -| 32 | Instance creation script hash (complete script is provided alongside if needed) -| 32 | Instance reading script hash (same) -| 32 | Instance consumption script hash (same) -| ... | Storage - -> The "primary bag input footprint" is computed as the concatenation of all *non created* token -> hashes in the primary bag, while the nonce is an arbitrary value. With this the new token hash -> only depends of the token data and the provided tokens in the bag, and remove any malleability -> while inserted in a state update. All tokens in a bag must have a distinct hash, the nonce -> allowing to create multiple tokens with the same data with distinct hashes. - -> All bags used as *primary bags* must contain a consumed token to avoid created tokens in different -> transactions(or state updates) to have the same hash (which can't always checked fpr state -> updates). - -#### Token context - -| Size | Description -|:----:|:--- -| 32 | Token hash -| 32 | Token tree hash (filled with zeros if in the main tree) -| 2 | Usage -| 2 | Family script parameters storage size (in items) -| 2 | Instance script parameters storage size (in items) -| 2 | Family sub-scripts count -| 2 | Instance sub-scripts count -| | -| ... | Family script parameters storage -| ... | Instance script parameters storage -| ... | Family sub-scripts hashes (complete sub-scripts are provided alongside) -| ... | Instance sub-scripts hashes (complete sub-scripts are provided alongside) - -Usage : - -| Value (bits) | Description -|:----------:|:----- -| `00______ ________` | Token is read (not consumed) -| `01______ ________` | Token is consumed -| `10______ ________` | Token is created - -> TODO : Find a way to take less space for usage bits. - -The hash of this **token context** is called the **token context footprint**. - -#### Tokens bag - -| Size | Description -|:----:|:--- -| 2 | Token context footprints count -| 2 | Storage size -| | -| ... | Token context footprints -| ... | Storage - -The **bag footprint** is computed as the hash the "Token context footprints" part. -Signatures are made on this footprint and stored in the *storage* part. - -A token script can then : - -- verify it's own footprint is signed -- verify another token footprint is signed -- verify a set of tokens footprints are signed together -- don't verify if its footprint is signed - -#### Transaction - -| Size | Description -|:----:|:--- -| 2 | Read/consumed tokens count -| 2 | Created tokens count -| 2 | Agregated execution contexts count -| | -| ... | Read/consumed tokens execution contexts -| ... | Created tokens execution contexts -| ... | Agregated execution contexts - -#### Merkle tree - -Tokens are stored in a Merkle tree to remove the need for nodes to store the complete set of tokens. -With transactions Merkle proofs are given to show that provided tokens are indeed in the current set -of available tokens. - -First, tokens are inserted in a fixed-depth tree, always at the deepest level. For a 3 deep tree, -we have : - -```txt - - root - ____/\____ - / \ - /\ /\ - / \ / \ - / \ / \ - /\ /\ /\ /\ -0 1 2 3 4 5 6 7 -``` - -Empty branches or leaves have a hash of `0x0000..0000`. To proove the existence of a token, we can -provide only the path from the token leaf to the root. - -```txt - - root - ____/\____ - / \ - /\ hash -hash \ - \ - /\ - hash 3 -``` - -If the token is consumed in the transaction, we replace the token hash with `0x0000..0000` and -thanks to the Merkle proof we can calculate the new root. All hashes updates can be applied to -other stored token proofs to make them valid in the new Merkle tree. - -This structure has a limited size. When a tree is full, we create a new one and combine the 2 -with a new root. - -```txt - /\ - / tree2 - /\ - / tree1 - /\ -nothing tree0 -``` - -A node only need to stores the Merkle proof of the next insertion position to be able to insert new -tokens in the tree. - -> New tokens can be inserted in place of now deleted old tokens to spare new slot and slow down -> proof size increase. \ No newline at end of file diff --git a/whitepaper.md b/whitepaper.md new file mode 100644 index 0000000000000000000000000000000000000000..e88fc159ec719831a78385d69df0d4aa832bc674 --- /dev/null +++ b/whitepaper.md @@ -0,0 +1,35 @@ +# FYgg : A Generic Decentralised Operating System Network + +## Introduction + +**FYgg** is a **decentralised operating system** protocol managing permissioned **tokens** +that can represent programs, states, assets or even currency units. A token can have children an +defines how they can be **created**, **provided**, **updated** or **destroyed** in a specialized +**pure functionnal programming language**. The protocol *as is* is **usage-agnostic** and unable +to perform any task of it's own except running the *root token* main function, and its power comes +from the ability of tokens to program how them and their children can be used. These programs are +not meant to perform complex calculation, but only to verify the new state is valid. + +When created a token is assigned a **unique and definitive ID**, while it also have a **state ID** +changing each time the token is updated to avoid *replay attacks*. Children are stored in a +**Merkle tree** structure, the parent storing the **Merkle root** of the tree while the +**Merkle proof** of the children must be provided when it's used. Thanks to this it's possible to +discard any token while begin able to verify **state updates** (or **transformations**) if all used +tokens and their proofs are provided. + +**Transformations** (or *transforms* for short) describes changed in a group of tokens. It list +tokens which are used together and can store additionnal data (such as signatures) which can be used +to verify their validity. A token can be used in multiple transforms if multiple sub-groups of +tokens require different additionnal data. Each of these individual transforms can be invalid but as +a whole become valid. A transform stores a list of transforms it depends on (sub-groups transforms +or child token transforms). These dependencies make a **directed acyclic graph** which can be +used in token programs to verify rules. + +By default, many things are not verified automatically and are dangerous unless they are check +manually by token programs. By this construct it's possible to create really complex systems which +could not be created otherwise while allowing to make a globally secure tree. For exemple, it's +possible by default to create a token with a *subtree Merkle root* **without** providing nor +verifying its children. Most tokens will forbid this, but it can be used to import a large amount of +somehow trusted tokens into the tree. The main usage is cross-tree communication with trust coming +from an user-based oracle (detailed later in this document), allowing bandswitch and computation +sharding between multiple independent trees. \ No newline at end of file