Skip to content
Snippets Groups Projects

WIP: RFC 5 : New Scalable Blockchain Protocol

Closed nanocryk requested to merge rfc5-duniter-protocol-rework into master
Compare and
1 file
+ 687
0
Compare changes
  • Side-by-side
  • Inline
+ 687
0
 
# #5 Duniter Protocol Rework (V11)
 
 
```txt
 
RFC: 5
 
Title: Duniter Protocol Rework (V11)
 
Type: Hard-fork
 
Status: WIP
 
Author: nanocryk <nanocryk@duniter.org>
 
Created: 2018-01-29
 
Last edited: 2018-01-30
 
License: AGPL-3
 
```
 
 
This document provide specifications of a reworked protocol for the Duniter project.
 
 
It aims to provide an efficient and strong base for future developments by taking the actual
 
protocol (version 10), simplifying it and adding usefull elements to increase performance and
 
extensibility.
 
 
This document is written in a "no previous knowledge" fachion to allow anyone to understand it,
 
and will allow to directly use it as documentation if changes are accepted and implemented.
 
 
> This document is in writing process and may not be complete nor accurate. Reviews and comments
 
> are welcome.
 
 
## Summary
 
 
1. [A brief description of Duniter](#1-a-brief-description-of-duniter)
 
1. [Protocol conventions](#2-protocol-conventions)
 
1. [Keys, addresses and accounts.](#3-keys-addresses-and-accounts)
 
1. Identities and the Web of Trust
 
1. Transactions between accounts
 
1. In depth block structure
 
1. Deployement plan
 
 
## 1. A brief description of Duniter
 
 
The **Duniter software** aims to provide a **Universal *Dividend** based crypto-currency based on
 
*Stephane Laborde's [Relative Theory of Money]*. It aims to provide money creation equality between
 
all users of the currency in space [of users] and time [users join and leave]. Money is
 
co-created by all the users and this process is automated by **Duniter**, allowing any user without
 
any technical skills to take part of the money creation. The name is made of `D + unit + er` as "a tool to create UD units".
 
 
[Relative Theory of Money]: http://en.trm.creationmonetaire.info/
 
 
Each *Duniter* currency is built on a consecutive list of **blocks** linked together using
 
[cryptographic hashes], hense the name **blockchain**. Each block represent a new valid state of the
 
system and contains data to transform this valid state into a new valid state. This process is
 
applyed by any nodes in the network to ensure changes meet consensus.
 
 
Each block store the *proof of integrity* of the state and transformations as the *root* of a
 
[Merkle tree] (the Merkle root). This *Merkle root* needs to have specific properties to be
 
considered valid and computationnal work is needed to satisfy them. This process is called a
 
**Proof of Work** and allow to randomly pick writer for the next block, preventing an individual or
 
a group to take control of the currency.
 
 
[cryptographic hashes]: https://en.wikipedia.org/wiki/Cryptographic_hash_function
 
[Merkle tree]: https://en.wikipedia.org/wiki/Merkle_tree
 
 
Since we want to provide a *Universal Dividend*, we need to ensure that a real living user can
 
only have one identity per currency. To avoid computationnal attacks on the blockchain, we also
 
desire to have a "one user, one vote" *Proof of Work* system. To achieve this we use a
 
[Web of Trust] between members. Each member can give and receive certifications to allow other
 
identities to become and stay a member. This *Web of Trust* is stored in the blockchain, and
 
only *members* are allowed to write blocks. Thus, the *blockchain* is secured from the inside and
 
can't be easily attacked by external entities. The *Web of Trust* have more rules to resist attacks
 
which will be discribed later in this document.
 
 
[Web of Trust]: https://en.wikipedia.org/wiki/Web_of_trust
 
 
## 2. Protocol conventions
 
 
### Data format
 
 
Documents are structured and stored in binary formats to allow efficient storage, network
 
transmission and reading. All data is [big-endian] unless otherwise specified and [aligned] in 4
 
bytes blocks to improve memory speeds. All given sizes are given in *bytes* unless otherwise
 
specified.
 
 
[big-endian]: https://en.wikipedia.org/wiki/Endianness
 
[aligned]: https://en.wikipedia.org/wiki/Data_structure_alignment
 
 
### Hashes
 
 
*Cryptographic hashes* are done with the [SHA-256] algorithm unless otherwise specified. They are
 
stored as raw bytes arrays and should be displayed in hexadecimal format.
 
 
[SHA-256]: https://en.wikipedia.org/wiki/SHA-2
 
 
### Formating
 
 
Some formats are used to improve display or storage of some data :
 
 
- **Base58** (display) : Mainly used for keys, it avoids using close looking
 
characters and allow whole content selection with double-clicking.
 
 
The alphabet is `123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`.
 
- **Base64** (display) : Data format used for non user-friendly data such as signatures.
 
 
The alphabet is `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`.
 
- **Name64** (storage) : Allow to store names in a more compact way that raw ASCII/UTF-8 text.
 
Each character is stored on 6bits, and prevent any invalid characters.
 
 
The alphabet is `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`.
 
 
### Block IDs and blockstamps
 
 
Each block is indexed by its **block ID** stored as a *4 bytes unsigned integer*.
 
The ***genesis block*** *ID* is `0`, and each following block have a *block ID* incremented
 
by `1`.
 
 
To refeer a *block*, we use it's **blockstamp** made of its *block ID* and its *Merkle root*.
 
The *blockstamp* of the genesis block *might be* `0-883228A23F8A75B342E912DF439738450AE94F5D`
 
and the *blockstamp* of block `433` *might be* `433-FB11681FC1B3E36C9B7A74F4DDE2D07EC2637957`.
 
 
Since hashes are stored on 32 bytes, a *blockstamp* is stored on a 36 bytes value.
 
 
> Note that is says "might be" because the hash is not known in advence.
 
 
### Currency values
 
 
> To simplify explanations, we'll work with Ğ1 currency as an example. The currency symbol be
 
> replaced by any other currency made with Duniter.
 
 
The smallest **unit** that can be stored is 1 mĞ1, or 0.001 Ğ1. To avoid any floating part, all
 
storage and calculations are made in mĞ1, and are displayed with other prefixes for
 
user-friendliness.
 
 
- 1 Ğ1 = 1 000 mĞ1 = 1 000 units
 
- 1 kĞ1 = 1 000 Ğ1 = 1 000 000 units
 
- 1 MĞ1 = 1 000 000 Ğ1 = 1 000 000 000 units
 
- 1 GĞ1 = 1 000 000 000 Ğ1 = 1 000 000 000 000 units
 
 
Currency values are stored as :
 
 
| Size | Data |
 
|:----:|:-----|
 
| *1 byte* | Base
 
| *7 bytes* | Signed value in units
 
 
> Value need to be signed to allow operations on them within scripts.
 
 
The real value is calculated as :
 
 
```txt
 
RealValue = Value * 10^Base
 
```
 
 
Since the base will grow forever, it needs to cycle. We can compare values in an interval of
 
`[-128;127]` around the main base.
 
 
> TODO : better explain ranges
 
 
This base incrementation will be very slow and a full cycle won't append until a long time. When the
 
UD becomes greater than `2^16` units, we increment the base.
 
 
We also need to update the displayed value, as it will be impractical to display them as very large
 
numbers. A suggested solution is to talk about *Dunes* or *Ď1* as a *Dividend Ğ1*, since *Ď1* are
 
not going to grow exponentialy.
 
 
### Dates
 
 
All dates are stored in [UNIX timestamp format], as the number of seconds
 
since 00:00:00 UTC on January 1, 1970. They are stored in a 64bit format to
 
avoid [year 2038 problem]. In this format the counter will overflow
 
in approximately 293 billion years.
 
 
Durations are expressed in eleapsed time between 2 *timestamps*.
 
 
Another way to provide dates is to reference a *blockstamp*.
 
Dates in the *blockchain* are calculated as the average time provided in a window of
 
`MedianTimeBlocks` blocks. It should be preferred to use *blockstamps* since its independent
 
of any external influences.
 
 
> `MedianTimeBlocks = 24` in Ǧ1 currency.
 
 
[UNIX timestamp format]: https://en.wikipedia.org/wiki/Unix_time
 
[year 2038 problem]: https://en.wikipedia.org/wiki/Unix_time#Representing_the_number
 
 
## 3. Keys, addresses and accounts
 
 
To allow funds to be spent only by authorized users, we make us of [Public-key cryptography].
 
User can generate `(public key, private key)` pairs, use the **private key** to sign data and get
 
a **signature**, and **verify** this *signature* with the the associated *public key*.
 
 
[Public-key cryptography]: https://en.wikipedia.org/wiki/Public-key_cryptography
 
 
Cryptographic data are stored in a special format to allow :
 
 
- store the type of data it contains
 
- linking a key with a specific currency to avoid cross-blockchain [replay attacks].
 
- provide a checksum to detect typing errors
 
 
[replay attacks]: https://en.wikipedia.org/wiki/Replay_attack
 
 
This format is structured as :
 
 
| Size | Data |
 
|:----:|:-----|
 
| 4 | Checksum
 
| 2 | Currency code
 
| 2 | Data type (determine `size` of payload)
 
| `size` | Payload
 
 
If the *data type* is `0`, the payload is an **account** and can represent anything holding funds
 
(a single key signature, a multi-signature, a smart contract, etc). It's stored on *32 bytes* and
 
its computing will be detailed later in this document. It has no associated signature scheme and
 
can't be used to create an identity.
 
 
Other values store cryptographic keys discribed in this table :
 
 
| Data type | Payload size | Description
 
|:---------:|:------------:|:------
 
| 2 | 32 | [ed25519] public key
 
| 3 | 64 | [ed25519] private key
 
 
[ed25519]: https://en.wikipedia.org/wiki/EdDSA
 
 
> More key types may be added in the future.
 
 
The *hash* of all fields except the *checksum* is called an **address** and have a fixed size of
 
*32 bytes*. When a *complete public key* is used, it can be hashed and compared with the
 
*compact key*. It can be used to hide the public key before spending and provide security even if
 
the cryptographic algorithm is broken.
 
 
The *checksum* is equal to the first 4 bytes of the *compact key*.
 
 
> With this format it will be very unlikely someone send to an unwanted address.
 
 
-----
 
 
> This document is being rewrited with a new structure.
 
> Chapters not migrated yet are kept here until they are inserted in the new
 
> protocol description.
 
 
## 2. Conventions
 
 
### 2.8. Identities
 
 
Each identity can be referred as its **identity hash** (or **indentity UID**) computed from
 
the username, the hash of its associated *compact key* and the *blockstamp* of the identity
 
creation document.
 
 
```txt
 
IdentityHash = SHA256(Username + CompactKey + Blockstamp)
 
```
 
 
> The `+` operation is a raw byte concatenation.
 
 
## 3. General document format
 
 
Each *document* is composed of a **header**, a **payload** and one or more **signatures**.
 
The tuple `(currency code, document type)` is used in signatures,
 
but is ellided when written into a block since they can be deduced from block data and context.
 
This prevent documents from other currencies to be compatible.
 
 
An **extention field** is provided to allow future protocol extensions without modifying this
 
document structure. It can contain any data but should have some sort of standard format to
 
target specific extensions. This format is not yet defined and will be in a future RFC, for
 
now this extension field should be empty (size of 0).
 
 
The *header* and *payload* are hashed to optain a **document ID**, then *signatures* are made
 
from it.
 
 
The header is composed of :
 
 
| Size | Data |
 
|:----:|:-----|
 
| *2 bytes* | Currency code
 
| *2 bytes* | Document type
 
| *2 bytes* | Payload size in bytes
 
| *2 bytes* | Number of issuers
 
| ... | List of issuers *complete public keys* with alignement padding for each
 
| *1 byte* | Extension field size in bytes (0 to 255)
 
| ... | Extension field with alignement padding
 
 
Payload and each signatures have alignement padding.
 
 
Cryptographic systems of signatures are not provided and matching public key types are used.
 
A document is valid if each public key can match a signature (with 0 bytes left and no
 
overflows) and each signature is valid for the document content and the public key.
 
 
The document types are the following :
 
 
| Name | Code |
 
|:-----|:----:|
 
| Block | `0x00` |
 
| Transaction | `0x10` |
 
| Identity | `0x20` |
 
| Membership / Leaver | `0x21`/`0x22` |
 
| Certification | `0x23` |
 
| Revocation | `0x24` |
 
 
## 4. Identity document
 
 
| Size | Data |
 
|:----:|:-----|
 
| *36 bytes* | HEAD blockstamp while creating this document |
 
| *1 byte* | Username length (1 to 127) |
 
| ... | Username in *Name64* format *(with alignement padding)*
 
 
Username must not be used if any *identity document* present in the blockchain already uses it : active or revoked. We could also take account of *identity documents* in the pool, but since
 
pools have no consensus, it can't be ensured by the network.
 
 
Identity *validy frames* will be computed from the given blockstamp wich is at most the last
 
blockstamp at time of signature. It prevent someone to create an identity "in the future" and
 
allow to have duration calculation based on *signature time* and not *block insertion time*.
 
These validy frames are currency parameters and will be describes in more details further in
 
this document.
 
 
This document must only have one issuer. With this one issuer *public key* we can compute
 
its *compact key* and with the *username* and the *blockstamp* we can compute its
 
*identity hash*.
 
 
## 5. Membership document
 
 
| Size | Data |
 
|:----:|:-----|
 
| *36 bytes* | HEAD blockstamp while creating this document |
 
| *32 bytes* | Identity hash
 
 
If the document code is `0x21`, it's an opt-in.
 
 
If the document code is `0x22`, it's an opt-out.
 
 
## 6. Certification document
 
 
| Size | Data |
 
|:----:|:-----|
 
| *36 bytes* | HEAD blockstamp while creating this document |
 
| *32 bytes* | Target identity hash
 
 
## 7. Revocation document
 
 
| Size | Data |
 
|:----:|:-----|
 
| *4 bytes* | Filled with zeros
 
| *32 bytes* | Identity hash to revocate
 
 
To allow usage of *version 10* text-based revocation document, we have this
 
structure if the first field is different from 0 :
 
 
| Size | Data |
 
|:----:|:-----|
 
| *4 bytes* | Length of text (in characters)
 
| ... | V10 Revocation document text *(with alignement padding)*
 
 
In this case, there must no issuers and signatures, since they are contained in
 
the text document.
 
 
## 8. Transaction document
 
 
A **transaction document** describes the transfer of value from **source addresses** to
 
**outputs addresses**. The **sum of *inputs* values must equal the sum of *output* values**.
 
 
Each *output* describes spending conditions using a **script** system which will be
 
described below.
 
 
| Size | Data |
 
|:----:|:-----|
 
| *36 bytes* | HEAD blockstamp while creating this document
 
| *1 byte* | Number of inputs |
 
| *1 byte* | Number of outputs |
 
| *2 bytes* | *(padding)* |
 
|
 
| | **For each source** : |
 
| *32 bytes* | Source : `hash(address, index)` |
 
| *8 bytes* | Currency value taken from this address |
 
| ... | *Unlock parameters (with alignement padding with `Nop` opcodes)* |
 
|
 
| | **For each output** : |
 
| *8 bytes* | Currency value to send at this address |
 
| ... | *Lock script (with alignement padding with `Nop` opcodes)* |
 
 
Each time source is used, it become unusable by another transaction. To use
 
this address again, you'll need to provide `hash(address, index+1)`. This prevent
 
replay attacks (using a transaction multiple time to steal funds). The complete
 
mechanism will be described later in this document.
 
 
> The following script system is version `0`. Any other version is an "anyone-can-spend"
 
> and should be treated with care by light clients.
 
 
## 9. Script system
 
 
> This system is heavily inspired by Bitcoin script system discribed
 
> [here](https://en.bitcoin.it/wiki/Script). It adds to it transaction data reflection
 
> (such as outputs, amounts); merkelized scripts and multiple cryptographic systems
 
> support.
 
 
The script system is simple, **stack-based** and processed from left to right. It is intentionnaly
 
**not Turing-complete, with no loops**.
 
 
The stack hold *byte arrays*. When used as numbers, byte arrays are interpreted as
 
**big-endian variable-length integers** with two's complement for sign handling. 0 can also be
 
represented by a null-length array. Byte array are interpreted as *booleans* where `false`
 
is represented by 0 and `true` by any other value.
 
 
A **main stack** and **alt stack** are available and empty by default. The executed script is
 
the concatenation of the *unlock parameters* and the *lock script*. Thus the
 
*unlock parameters* is a script putting data onto the stack which will be used by the *lock script*.
 
 
A *transaction* is valid if nothing in the script triggers a failure, the main stack contains
 
only one `true` value and the alt stack is empty.
 
 
> We'll refeer to the **main stack** as **the stack** and precise **alt stack** when necessary.
 
 
### Opcodes
 
 
| Opcode | Hex | Word | Input | Output | Description |
 
|:------:|:---:|:-----|:------|:-------|:------------|
 
| | | | | | **Constants**
 
| `0` | `0x00` | `C0`, `Zero`, `False` | *none* | *empty value* | An empty array is pushed on the stack.
 
| `1-75` | `0x01-0x4b` | `PushData1-PushData75` | *special* | *data* | The next *opcode* bytes is data to be pushed on the stack.
 
| `76` | `0x4c` | `PushData1B` | *special* | *data* | The next byte contains the number of bytes to be pushed on the stack.
 
| `77` | `0x4d` | `PushData2B` | *special* | *data* | The next two bytes contains the number of bytes to be pushed on the stack.
 
| `78` | `0x4e` | `PushData4B` | *special* | *data* | The next four bytes contains the number of bytes to be pushed on the stack.
 
| `80` | `0x50` | `CN1`, `NegOne`| *nothing* | `-1` | The number -1 is pushed onto the stack.
 
| `81` | `0x51` | `C1`, `One`, `True` | *nothing* | `1` | The number 1 is pushed onto the stack.
 
| `82-96` | `0x52-0x60` | `C2-C16` | *nothing* | `2-16` | The number in the word name (2-16) is pushed onto the stack.
 
|
 
| | | | | | **Flow control**
 
| `97` | `0x61` | `Nop` | *nothing* | *nothing* | Does nothing.
 
| `98` | `0x62` | `If` | `condition` | *nothing* | If the top stack value (`condition`) is not `false`, opcodes until an `Else` or `Fi` are executed, otherwise they are ignored. The top stack value is always removed.
 
| `99` | `0x63` | `IfNot` | `condition` | *nothing* | If the top stack value (`condition`) is `false`, opcodes until an `Else` or `Fi` are executed, otherwise they are ignored. The top stack value is always removed.
 
| `100` | `0x64` | `Else` | *nothing* | *nothing* | If the preceding `If`/`IfNot` was not executed then opcodes until a `Fi` are executed, otherwise they are ignored.
 
| `101` | `0x65` | `Fi` | *nothing* | *nothing* | Ends an if/else block. All blocks must end, or the transaction is **invalid**. A `Fi` without `If`/`IfNot` earlier is also not valid.
 
| `102` | `0x66` | `Assert`/`Verify` | `true`/`false` | *nothing* / *panic* | **Marks transaction as invalid** if top stack value in not `true`. The top stack value is removed.
 
| `103` | `0x67` | `Panic`/`Return` | *nothing* | *panic* | **Marks transaction as invalid.**
 
|
 
| | | | | | **Stack**
 
| `104` | `0x68` | `ToAltStack` | `xn .. x2 x1 x0 <n>` | `(alt) x0 x1 x2 .. xn` | Puts the `n` items on top of the main stack onto the top of the alt stack, one by one. Removes them from the main stack.
 
| `105` | `0x69` | `FromAltStack` | `(alt) xn .. x2 x1 x0 (main) <n>` | `x0 x1 x2 .. xn` | Puts the `n` items on top of the alt stack onto the top of the main stack, one by one. Removes them from the alt stack.
 
| `106` | `0x6a` | `Depth` | *nothing* | `<stack size>` | Puts the number of stack items onto the stack.
 
| `107` | `0x6b` | `IfDup` | `x` | `x`/`x x` | If the stop stack value is not `0`, duplicate it.
 
| `108` | `0x6c` | `Drop` | `x` | *nothing* | Removes the top stack item.
 
| `109` | `0x6d` | `Dup` | `x` | `x x` | Duplicate the top stack item.
 
| `110` | `0x6e` | `Nip` | `x1 x2` | `x2` | Removes the second-to-top stack item.
 
| `111` | `0x6f` | `Over` | `x1 x2` | `x1 x2 x1` | Copies the second-to-top stack item to the top.
 
| `112` | `0x70` | `Pick` | `xn ... x2 x1 x0 <n>` | `xn .. x2 x1 x0 xn` | The item `n` back in the stack is copied to the top.
 
| `113` | `0x71` | `Roll` | `xn ... x2 x1 x0 <n>` | `.. x2 x1 x0 xn` | The item `n` back in the stack is moved to the top.
 
| `114` | `0x71` | `Rot` | `x1 x2 x3` | `x2 x3 x1` | The top three item on the stack are rotated to the left.
 
| `115` | `0x72` | `Swap` | `x1 x2` | `x2 x1` | The top two items on the stack are swapped.
 
| `116` | `0x73` | `Tuck` | `x1 x2` | `x2 x1 x2` | The item at the top of the stack is copied and inserted before the second-to-top item.
 
| `117` | `0x74` | `Drop2` | `x1 x2` | *nothing* | Removes the top two stack items.
 
| `118` | `0x75` | `Dup2` | `x1 x2` | `x1 x2 x1 x2` | Duplicates the top two stack items.
 
| `119` | `0x76` | `Dup3` | `x1 x2 x3` | `x1 x2 x3 x1 x2 x3` | Duplicates the top three stack items.
 
| `120` | `0x77` | `Over2` | `x1 x2 x3 x4` | `x1 x2 x3 x4 x1 x2` | Copies the pair of items two spaces back in the stack to the front.
 
| `121` | `0x78` | `Rot2` | `x1 x2 x3 x4 x5 x6` | `x3 x4 x5 x6 x1 x2` | The fifth and sixth items back are moved to the top of the stack.
 
| `122` | `0x79` | `Swap2` | `x1 x2 x3 x4` | `x3 x4 x1 x2` | Swaps the top two pairs of items.
 
| `123` | `0x7a` | `IsEmpty` | `in` | `true`/`false` | Returns 1 if the top of the stack in a zero-length vector. It consumes the input, so if it needs to be used it should be duplicated first.
 
|
 
| | | | | | **Bitwise Logic**
 
| `128` | `0x80` | `Invert` | `in` | `out` | Flips all of the bits in the input.
 
| `129` | `0x81` | `BitAnd` | `x1 x2` | `out` | Bolean *and* between each bit in the inputs.
 
| `130` | `0x82` | `BitOr` | `x1 x2` | `out` | Bolean *or* between each bit in the inputs.
 
| `131` | `0x83` | `BitXor` | `x1 x2` | `out` | Bolean *exclusive or* between each bit in the inputs.
 
| `132` | `0x84` | `BitEqual` | `x1 x2` | `true`/`false` | Return 1 if the inputs are exactly equal, 0 otherwise.
 
|
 
| | | | | | **Arithmetic**
 
| | | | | | *Arithmetic inputs are limited to signed 64-bit integers, but may overflow their output.*
 
| `144` | `0x90` | `Add1` | `in` | `out` | 1 is added to the input.
 
| `145` | `0x91` | `Sub1` | `in` | `out` | 1 is subtracted from the input.
 
| `146` | `0x92` | `Negate` | `in` | `out` | The sign of the input is flipped.
 
| `147` | `0x93` | `Abs` | `in` | `out` | The input is made positive.
 
| `148` | `0x94` | `Not` | `in` | `out` | If the input is 0 or 1, it is flipped. Otherwise the output will be 0.
 
| `149` | `0x95` | `Not0` | `in` | `out` | Returns 0 if the input is 0, 1 otherwise.
 
| `150` | `0x96` | `Add` | `a b` | `out` | a is added to b.
 
| `151` | `0x97` | `Sub` | `a b` | `out` | b is subtracted from a.
 
| `152` | `0x98` | `And` | `a b` | `out` | If both a and b are not 0, the output is 1, otherwise 0.
 
| `153` | `0x99` | `Or` | `a b` | `out` | If a or b in not 0, the output is 1, otherwise 0.
 
| `154` | `0x9a` | `NumEqual` | `a b` | `out` | Returns 1 if numbers are equal, otherwise 0.
 
| `155` | `0x9b` | `NumNotEqual` | `a b` | `out` | Returns 1 if numbers are not equal, otherwise 0.
 
| `156` | `0x9c` | `NumLessThan` | `a b` | `out` | Returns 1 if a is less than b, 0 otherwise.
 
| `157` | `0x9d` | `NumGreaterThan` | `a b` | `out` | Returns 1 if a is greater than b, 0 otherwise.
 
| `158` | `0x9e` | `NumLessThanOrEqual` | `a b` | `out` | Returns 1 if a is less than or equal to b, 0 otherwise.
 
| `159` | `0x9f` | `NumGreaterThanOrEqual` | `a b` | `out` | Returns 1 if a is greater than or equal to b, 0 otherwise.
 
| `160` | `0xa0` | `Min` | `a b` | `out` | Returns the smaller of a and b.
 
| `161` | `0xa1` | `Max` | `a b` | `out` | Returns the larger of a and b.
 
| `162` | `0xa2` | `Within` | `x min max` | `out` | Returns 1 if x is within the specified range (left-inclusive), 0 otherwise.
 
| `163` | `0xa3` | `Sum` | `xn .. x2 x1 x0 <n>` | `out` | Returns the sum of the `n` top values from the stack.
 
| | | | | | ***Arithmetic operations on currency values (takes account of the base) :***
 
| `164` | `0xa4` | `CurrencyEqual` | `a b` | `out` | Returns 1 if numbers are equal, otherwise 0.
 
| `165` | `0xa5` | `CurrencyNotEqual` | `a b` | `out` | Returns 1 if numbers are not equal, otherwise 0.
 
| `166` | `0xa6` | `CurrencyLessThan` | `a b` | `out` | Returns 1 if a is less than b, 0 otherwise.
 
| `167` | `0xa7` | `CurrencyGreaterThan` | `a b` | `out` | Returns 1 if a is greater than b, 0 otherwise.
 
| `168` | `0xa8` | `CurrencyLessThanOrEqual` | `a b` | `out` | Returns 1 if a is less than or equal to b, 0 otherwise.
 
| `169` | `0xa9` | `CurrencyGreaterThanOrEqual` | `a b` | `out` | Returns 1 if a is greater than or equal to b, 0 otherwise.
 
| `170` | `0xaa` | `CurrencyMin` | `a b` | `out` | Returns the smaller of a and b.
 
| `171` | `0xab` | `CurrencyMax` | `a b` | `out` | Returns the larger of a and b.
 
| `172` | `0xac` | `CurrencyWithin` | `x min max` | `out` | Returns 1 if x is within the specified range (left-inclusive), 0 otherwise.
 
| `173` | `0xad` | `CurrencySum` | `xn .. x2 x1 x0 <n>` | `out` | Returns the sum of the `n` top values from the stack.
 
|
 
| | | | | | **Crypto**
 
| `176` | `0xb0` | `Hash` | `value algo` | `hash` | The input is hashed using `algo` hashing algorithm. The list of algorithms is available below.
 
| `177` | `0xb1` | `CheckSig` | `sig pubkey` | `true`/`false` | The signature must be a valid signaure for the hash of this (the spending) transaction and public key. If it is, 1 is returned, 0 otherwise.
 
| `178` | `0xb2` | `CheckSigHash` | `sig pubkey compactkey` | `true`/`false` | Same as `CheckSig`, but `compactkey` must correspond to `pubkey`. With this opcode `pubkey` can be provided only at spending, thus protecting it for cryptographic attacks.
 
| `179` | `0xb3` | `CheckMultiSig` | `sig1 sig2 ... pub1 pub2 ... <count>` | valid sig count | Verify each pair `(sign, pubn)`, return the sumber of valid transactions.
 
| `180` | `0xb4` | `CheckMultiSigHash` | `sig1 sig2 ... pub1 pub2 ... compact1 compact2 <count>` | valid sig count | Combinaison of `CheckSigHash` and `CheckMultiSig`.
 
| `181` | `0xb5` | `Eval` | `script hash` | *special* | Evaluate `script` as if it was in-place. The script must have a Merkle Root equals to `hash`. If not, **transaction is invalid**. If the script *panic* (says the transaction is invalid), the **transaction is invalid**. The script hashing algorithm is described later in this document.
 
| `182` | `0xb6` | `Unused` | *special* | *empty value (false)* | Returns an empty value. The `(opcode + hash)` of this instruction is the **next 33 bytes in the script**. It allow to only provide hashes of unused code when using `Eval` opcode. Can only be used in *unlock parameters* and an output having an `Unused` opcode in its lock script is **invalid**.
 
|
 
| | | | | | **Data fetching**
 
| `193` | `0xc1` | `FetchSourceBlockTime` | *nothing* | `timestamp blockid` | Returns the timestamp and blockid corresponding to the block in which the source transaction document appears. One of the 2 dates can be discarded with `Drop` or `Nip` opcodes.
 
| `194` | `0xc2` | `FetchTargetBlockTime` | *nothing* | `timestamp blockid` | Returns the timestamp and blockid corresponding to the block in which the spending transaction document appears. One of the 2 dates can be discarded with `Drop` or `Nip` opcodes. It can be used to prevent using a source based on the date of the spending transaction.
 
| `195` | `0xc3` | `FetchDeltaBlockTime` | *nothing* | `delta_timestamp delta_blockid` | eturns the difference of timestamp and blockid between the block in which the spending transaction document appears and the spending transaction.One of the 2 durations can be discarded with `Drop` or `Nip` opcodes. It can be used to prevent using a source based on the duration before spending.
 
| `196` | `0xc4` | `FetchOutputAmount` | `output_index` | `amount base`/*empty* *empty* | Returns the amount spent by a specific output. Returns an empty value if this index is out of bound.
 
| `197` | `0xc5` | `FetchOutputAddress` | `output_index` | `address`/*empty* | Returns the script hash (address) of a specific output. Returns an empty value if this index is out of bound. It can be used to force specific conditions for an output.
 
 
Any undefined operators return the value `1`/`true` and doesn't mark the transaction as invalid.
 
If use before a `Assert`/`Verify` opcode, they won't mark the transaction as invalid easer.
 
Changing them to new opcodes will only restrict the set of valid transactions and outdated client will never see new opcodes as invalid.
 
With this setup we can add new backward-compatible features.
 
 
> Client should show warning when they see an unknown opcode since they could be
 
> out of date and assuming a new defined opcode is still an "anyone-can-spend" script.
 
 
Padding is done through `Nop` operators, and any leading `Nop` opcodes will be discarded
 
before any treatment.
 
 
### Hashing algorithms list
 
 
| Code | Name |
 
|:----:|:-----|
 
| `0` | SHA-256
 
 
Any other hashing code will return an *empty value*.
 
 
> More hashing algorithms will be added later.
 
 
### Script examples
 
 
To simplify our scripts examples, we write constants as `<data>` fields, and the stack push
 
is implied.
 
 
#### Classic pay-to-pubkey script
 
 
```txt
 
Script : <pubkey> CheckSig
 
Parameters : <sig>
 
```
 
 
Here is a step by step execution of the script
 
 
| Stack | Script | Description |
 
|:------|:-------|:------------|
 
| | `<sig> <pubkey> CheckSig` | Script and parameters are merged.
 
| `<sig> <pubkey>` | `CheckSig` | Data is pushed on the stack.
 
| `true` | | Signature is checked from top two stack items.
 
 
There is only `true` in the stack, so this transaction is valid.
 
 
#### Pay-to-compact-key script
 
 
```txt
 
Script : <compact key> CheckSigHash
 
Parameters : <sig> <pubkey>
 
```
 
 
#### 2-of-3-multisig script
 
 
```txt
 
Script : <compact1> <compact2> <compact3> 3 CheckMultiSigHash 2 NumGreaterThanEqual
 
Parameters : <sig1> <empty> <sig3> <pubkey1> <empty> <pubkey3>
 
```
 
 
### Script hashing
 
 
We must find a way to translate a stack-based script into a graph of dependency between
 
operations. Each operator consumes inputs and produces outputs than can be used to build
 
a graph. It's not a tree since a value can be used multiple time with a `Dup` opcode, but it
 
should not cause problems in bluiding a Merkle Tree with duplicated branches.
 
 
Each opcode becomes a node of the tree, and each producer of its input is a child, and the
 
consumers of its outputs are parents.
 
 
Let's build a 1-of-2-multisig script with separated checks :
 
 
```txt
 
Script : <compact key a> CheckSigHash 1 ToAltStack
 
<compact key b> CheckSigHash 1 FromAltStack
 
Or
 
```
 
 
We have a first opcode pushing `<compact key a>` on the stack. Then `CheckSigHash` consume
 
it and some input parameters, and push the result on the stack. The opcode `<compact key a>`
 
is a child of `CheckSigHash`. We can apply this rule to all of the operators to obtain this
 
tree :
 
 
```txt
 
-------Or--------
 
| |
 
---FromAltStack--- |
 
| | |
 
---ToAltStack-- 1 |
 
| | |
 
CheckSigHash 1 CheckSigHash
 
| |
 
<compact key a> <compact key b>
 
```
 
 
If an operator have multiple children, we add them in a tree in the same order as the inputs.
 
Here `ToAltStack` take in input `xn ... x2 x1 x0 <n>`, so they are inserted in the tree in
 
the same order from right to left.
 
 
The rules for the hash of an opcode are :
 
 
- If it consumes items from stacks, we add `SHA-256(SHA-256(child1) + SHA-256(child2) + ...)`
 
- If it provide data (`PushDataX` opcodes), we add `SHA-256(data)`
 
- We then hash all the above with `SHA-256`.
 
- We prefix the opcode.
 
 
The only exception is the `Unused` opcode having the `(opcode, hash)` pair in the 33 following bytes. This is
 
used to hide the unused branches at spending.
 
 
Exemple :
 
 
```txt
 
C4 PushData1B <data on 4 bytes>
 
```
 
 
becomes
 
 
```txt
 
PushData1B
 
+ SHA-256(
 
+ SHA-256(C4)
 
+ SHA-256(<data on 4 bytes>)
 
)
 
```
 
 
An opcode can be replaced by an `Unused` opcode **only if it always push one boolean value (0 or 1) on the main stack**. `Unused` will push `false` on the stack *as if* the underlying branch returned false.
 
 
In the above example only the 2 `CheckSigHash` and the `Or` can be replaced by their hash.
 
Note that it's praticaly no possible to replace the `Or`, since it will return `false` and
 
the transaction will be invalid.
 
 
If we consider `<script_hash>` as the Merkle Root of the above script, we can have as a lock script :
 
 
```txt
 
<script_hash> Eval
 
```
 
 
Then at spending we should have as parameters :
 
 
```txt
 
<sig a> <pubkey a>
 
[
 
<compact key a> CheckSigHash 1 ToAltStack
 
Unused [CheckSigHash <branch hash>] 1 FromAltStack
 
Or
 
] -- this script is pushed in one byte array on top of the stack
 
```
 
 
or
 
 
```txt
 
[
 
<sig b> <pubkey b>
 
Unused [CheckSigHash <branch hash>] 1 ToAltStack
 
<compact key b> CheckSigHash 1 FromAltStack
 
Or
 
] -- this script is pushed in one byte array on top of the stack
 
```
 
 
In each case, the `Unused` opcode returns `false` but the other returns `true`, so `Or`
 
return `true`.
 
 
### Allow usage of V10 outputs
 
 
To allow spending of transaction in V10 format, we must find a way to translate
 
the old scripts in this new format and have the exact same behavior. When a node see a V10
 
source, it convert its V10 script into a V11, and execute it. It means that we spend a V10
 
script with V11 parameters, and a client also need to do this translation to know in which
 
order add data onto the stack. Note that in the new format, it will be required to
 
duplicate a parameter if it's used multiple times.
 
 
| V10 script | V11 script | V10 parameters | V11 parameters
 
|:-----------|:------------|:---------------|:----
 
| `SIG(pubkey)` | `<pubkey> CheckSig` | `SIG(sig_index)` | `<signature>`
 
| `XHX(sha256_hash)` | `1 Hash <sha256_hash> BitEqual` | `XHX(pass)` | `<pass>`
 
| `CLVT(timestamp)` | `FetchSourceBlockTime Drop <timestamp> NumGreaterThanOrEqual` | *nothing* | *nothing*
 
| `CSV(delay)` | `FetchDeltaBlockTime Drop <delay> NumGreaterThanOrEqual` | *nothing* | *nothing*
 
|
 
| `{X} AND {Y}` | `{X} 1 ToAltStack {Y} 1 FromAltStack And` | `{X} {Y}` | `{Y} {X}`
 
| `{X} OR {Y}` | `{X} 1 ToAltStack {Y} 1 FromAltStack Or` | `{X} {Y}` | `{Y} {X}`
 
 
> TODO : Need peer reviewing since it's a critical part of this protocol change.
Loading