Add process for making architectural changes
This commit is contained in:
@ -1,181 +0,0 @@
|
||||
# Smart Contracts Engine
|
||||
|
||||
The goal of this RFC is to define a set of constraints for APIs and smart contracts runtime such that we can execute our contracts safely on massively parallel hardware such as a GPU.
|
||||
|
||||
## Version
|
||||
|
||||
Version 0.3
|
||||
|
||||
## Definitions
|
||||
|
||||
* Transaction - an atomic operation with multiple instructions. All Instruction must complete successfully for the transaction to be comitted.
|
||||
* Instruction - a call to a program that modifies Account token balances and Account specific userdata state. A single transaction may have multiple Instructions with different Accounts and Programs.
|
||||
* Program - Programs are code that modifies Account token balances and Account specific userdata state.
|
||||
* Account - A single instance of state. Accounts are looked up by account Pubkeys and are associated with a Program's Pubkey.
|
||||
|
||||
## Toolchain Stack
|
||||
|
||||
+---------------------+ +---------------------+
|
||||
| | | |
|
||||
| +------------+ | | +------------+ |
|
||||
| | | | | | | |
|
||||
| | frontend | | | | verifier | |
|
||||
| | | | | | | |
|
||||
| +-----+------+ | | +-----+------+ |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| +-----+------+ | | +-----+------+ |
|
||||
| | | | | | | |
|
||||
| | llvm | | | | loader | |
|
||||
| | | +------>+ | | |
|
||||
| +-----+------+ | | +-----+------+ |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| +-----+------+ | | +-----+------+ |
|
||||
| | | | | | | |
|
||||
| | ELF | | | | runtime | |
|
||||
| | | | | | | |
|
||||
| +------------+ | | +------------+ |
|
||||
| | | |
|
||||
| client | | solana |
|
||||
+---------------------+ +---------------------+
|
||||
|
||||
[Figure 1. Smart Contracts Stack]
|
||||
|
||||
In Figure 1 an untrusted client, creates a program in the front-end language of her choice, (like C/C++/Rust/Lua), and compiles it with LLVM to a position independent shared object ELF, targeting BPF bytecode. Solana will safely load and execute the ELF.
|
||||
|
||||
## Runtime
|
||||
|
||||
The goal with the runtime is to have a general purpose execution environment that is highly parallelizeable. To achieve this goal the runtime forces each Instruction to specify all of its memory dependencies up front, and therefore a single Instruction cannot cause a dynamic memory allocation. An explicit Instruction for memory allocation from the `SystemProgram::CreateAccount` is the only way to allocate new memory in the engine. A Transaction may compose multiple Instruction, including `SystemProgram::CreateAccount`, into a single atomic sequence which allows for memory allocation to achieve a result that is similar to dynamic allocation.
|
||||
|
||||
|
||||
### State
|
||||
|
||||
State is addressed by an Account which is at the moment simply the Pubkey. Our goal is to eliminate memory allocation from within the program itself. Thus the client of the program provides all the state that is necessary for the program to execute in the transaction itself. The runtime interacts with the program through an entry point with a well defined interface. The userdata stored in an Account is an opaque type to the runtime, a `Vec<u8>`, the contents of which the program code has full control over.
|
||||
|
||||
### Transaction structure
|
||||
```
|
||||
/// An atomic transaction
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Transaction {
|
||||
/// A digital signature of `account_keys`, `program_ids`, `last_id`, `fee` and `instructions`, signed by `Pubkey`.
|
||||
pub signature: Signature,
|
||||
|
||||
/// The `Pubkeys` that are executing this transaction userdata. The meaning of each key is
|
||||
/// program-specific.
|
||||
/// * account_keys[0] - Typically this is the `caller` public key. `signature` is verified with account_keys[0].
|
||||
/// In the future which key pays the fee and which keys have signatures would be configurable.
|
||||
/// * account_keys[1] - Typically this is the program context or the recipient of the tokens
|
||||
pub account_keys: Vec<Pubkey>,
|
||||
|
||||
/// The ID of a recent ledger entry.
|
||||
pub last_id: Hash,
|
||||
|
||||
/// The number of tokens paid for processing and storage of this transaction.
|
||||
pub fee: i64,
|
||||
|
||||
/// Keys identifying programs in the instructions vector.
|
||||
pub program_ids: Vec<Pubkey>,
|
||||
/// Programs that will be executed in sequence and commited in one atomic transaction if all
|
||||
/// succeed.
|
||||
pub instructions: Vec<Instruction>,
|
||||
}
|
||||
```
|
||||
|
||||
The Transaction structure specifies a list of Pubkey's and signatures for those keys and a sequentail list of instructions that will operate over the state's assosciated with the `account_keys`. For the transaction to be committed all the instructions must execute successfully, if any abort the whole transaction fails to commit.
|
||||
|
||||
### Account structure
|
||||
Accounts maintain token state as well as program specific memory.
|
||||
```
|
||||
/// An Account with userdata that is stored on chain
|
||||
pub struct Account {
|
||||
/// tokens in the account
|
||||
pub tokens: i64,
|
||||
/// user data
|
||||
/// A transaction can write to its userdata
|
||||
pub userdata: Vec<u8>,
|
||||
/// program id this Account belongs to
|
||||
pub program_id: Pubkey,
|
||||
}
|
||||
```
|
||||
|
||||
# Transaction Engine
|
||||
|
||||
At it's core, the engine looks up all the Pubkeys maps them to accounts and routs them to the `program_id` entry point.
|
||||
|
||||
## Execution
|
||||
|
||||
Transactions are batched and processed in a pipeline
|
||||
|
||||
```
|
||||
+-----------+ +-------------+ +--------------+ +--------------------+
|
||||
| sigverify |--->| lock memory |--->| validate fee |--->| allocate accounts |--->
|
||||
+-----------+ +-------------+ +--------------+ +--------------------+
|
||||
|
||||
+------------+ +---------+ +-=------------+ +--------------+
|
||||
--->| load data |--->| execute |--->| commit data |-->|unlock memory |
|
||||
+------------+ +---------+ +--------------+ +--------------+
|
||||
|
||||
```
|
||||
|
||||
At the `execute` stage, the loaded pages have no data dependencies, so all the programs can be executed in parallel.
|
||||
|
||||
The runtime enforces the following rules:
|
||||
|
||||
1. The `program_id` code is the only code that will modify the contents of `Account::userdata` of Account's that have been assigned to it. This means that upon assignment userdata vector is guarnteed to be `0`.
|
||||
2. Total balances on all the accounts is equal before and after execution of a Transaction.
|
||||
3. Balances of each of the accounts not assigned to `program_id` must be equal to or greater after the Transaction than before the transaction.
|
||||
4. All Instructions in the Transaction executed without a failure.
|
||||
|
||||
## Entry Point
|
||||
Execution of the program involves mapping the Program's public key to an entry point which takes a pointer to the transaction, and an array of loaded pages.
|
||||
|
||||
```
|
||||
pub fn process_transaction(
|
||||
tx: &Transaction,
|
||||
pix: usize,
|
||||
accounts: &mut [&mut Account],
|
||||
) -> Result<()>;
|
||||
```
|
||||
|
||||
|
||||
## System Interface
|
||||
```
|
||||
pub enum SystemProgram {
|
||||
/// Create a new account
|
||||
/// * Transaction::keys[0] - source
|
||||
/// * Transaction::keys[1] - new account key
|
||||
/// * tokens - number of tokens to transfer to the new account
|
||||
/// * space - memory to allocate if greater then zero
|
||||
/// * program_id - the program id of the new account
|
||||
CreateAccount {
|
||||
tokens: i64,
|
||||
space: u64,
|
||||
program_id: Pubkey,
|
||||
},
|
||||
/// Assign account to a program
|
||||
/// * Transaction::keys[0] - account to assign
|
||||
Assign { program_id: Pubkey },
|
||||
/// Move tokens
|
||||
/// * Transaction::keys[0] - source
|
||||
/// * Transaction::keys[1] - destination
|
||||
Move { tokens: i64 },
|
||||
}
|
||||
```
|
||||
The interface is best described by the `Instruction::userdata` that the user encodes.
|
||||
* `CreateAccount` - This allows the user to create and assign an Account to a Program.
|
||||
* `Assign` - allows the user to assign an existing account to a `Program`.
|
||||
* `Move` - moves tokens between `Account`s that are assosciated with `SystemProgram`. This cannot be used to move tokens of other `Account`s. Programs need to implement their own version of Move.
|
||||
|
||||
## Notes
|
||||
|
||||
1. There is no dynamic memory allocation. Client's need to call the `SystemProgram` to create memory before passing it to another program. This Instruction can be composed into a single Transaction with the call to the program itself.
|
||||
2. Runtime guarantees that when memory is assigned to the `Program` it is zero initialized.
|
||||
3. Runtime guarantees that `Program`'s code is the only thing that can modify memory that its assigned to
|
||||
4. Runtime guarantees that the `Program` can only spend tokens that are in `Account`s that are assigned to it
|
||||
5. Runtime guarantees the balances belonging to `Account`s are balanced before and after the transaction
|
||||
6. Runtime guarantees that multiple instructions all executed successfully when a transaction is committed.
|
||||
|
||||
# Future Work
|
||||
|
||||
* Continuations and Signals for long running Transactions. https://github.com/solana-labs/solana/issues/1485
|
@ -1,98 +0,0 @@
|
||||
# Consensus
|
||||
|
||||
The goal of this RFC is to define the consensus algorithm used in Solana. This proposal covers a Proof of Stake (PoS) algorithm that leverages Proof of History (PoH). PoH is a permissionless clock for blockchain that is available before consensus. This PoS approach leverages PoH to make strong assumptions about time among partitions.
|
||||
|
||||
|
||||
## Version
|
||||
|
||||
version 0.4
|
||||
|
||||
## Basic Design Idea
|
||||
|
||||
Nodes on the network can be "up" or "down". A node indicates it is up either by voting as a validator or by generating a PoH stream as the designated leader. Consensus is reached when a supermajority + 1 of the staked nodes have voted on the state of the network at a particular PoH tick count.
|
||||
|
||||
Nodes take turns being leader and generating the PoH that encodes state changes. The network can tolerate loss of connection to any leader by synthesizing what the leader ***would have generated*** had it been connected but not ingesting any state changes. The complexity of forks is thereby limited to a "there/not-there" skip list of branches that may arise on leader rotation periods boundaries.
|
||||
|
||||
|
||||
## Message Flow
|
||||
|
||||
1. Transactions are ingested at the current leader.
|
||||
2. Leader filters for valid transactions.
|
||||
3. Leader executes valid transactions on its state.
|
||||
4. Leader packages transactions into entries based off the longest observed PoH branch.
|
||||
5. Leader transmits the entries to validator nodes (in signed blobs)
|
||||
a. The set of supermajority + `M` by stake weight of nodes is rotated in round robin fashion.
|
||||
b. The PoH stream includes ticks; empty entries that indicate liveness of the leader and the passage of time on the network.
|
||||
c. A leader's stream begins with the tick entries necessary complete the PoH back to that node's most recently observed prior leader period.
|
||||
6. Validators retransmit entries to peers in their set and to further downstream nodes.
|
||||
7. Validators validate the transactions and execute them on their state.
|
||||
8. Validators compute the hash of the state.
|
||||
9. At specific times, i.e. specific PoH tick counts, validators transmit votes to the leader.
|
||||
a. Votes are signatures of the hash of the computed state at that PoH tick count
|
||||
10. Leader executes the votes as any other transaction and broadcasts them to the network
|
||||
a. The leader votes at that same height once a majority of stake is represented on the PoH stream *(open question: do leaders vote?)*
|
||||
11. Validators observe their votes and all the votes from the network.
|
||||
12. Validators vote on the longest chain of periods that contains their vote.
|
||||
|
||||
Supermajority is defined as `2/3rds + 1` vote of the PoS stakes.
|
||||
|
||||
|
||||
## Staking
|
||||
|
||||
Validators `stake` some of their spendable sol into a staking account. The stakes are not spendable and can only be used for voting.
|
||||
|
||||
```
|
||||
CreateStake(
|
||||
PoH count,
|
||||
PoH hash,
|
||||
source public key,
|
||||
amount,
|
||||
destination public key,
|
||||
proof of ownership of destination public key,
|
||||
signature of the message with the source keypair
|
||||
)
|
||||
```
|
||||
|
||||
Creating the stake has a warmup period of TBD. Unstaking requires the node to miss a certain number of validation voting rounds.
|
||||
|
||||
## Validation Votes
|
||||
|
||||
```
|
||||
Validate(
|
||||
PoH count,
|
||||
PoH hash,
|
||||
stake public key,
|
||||
signature of the state,
|
||||
signature of the message with the stake keypair
|
||||
)
|
||||
```
|
||||
|
||||
## Validator Slashing
|
||||
|
||||
Validators `stake` some of their spendable sol into a staking account. The stakes are not spendable and can only be used for voting.
|
||||
|
||||
```
|
||||
Slash(Validate(
|
||||
PoH tick count,
|
||||
PoH hash,
|
||||
stake public key,
|
||||
...
|
||||
signature of the message with the stake keypair
|
||||
))
|
||||
```
|
||||
|
||||
When the `Slash` vote is processed, validators should lookup `PoH hash` at `PoH count` and compare it with the message. If they do not match, the stake at `stake public key` should be set to `0`.
|
||||
|
||||
## Leader Slashing
|
||||
|
||||
The goal is to discourage leaders from generating multiple PoH streams. When this occurs, the network adopts ticks for that leader's period. Leaders can be slashed for generating multiple conflicting PoH streams during their period.
|
||||
|
||||
## Validation Vote Contract
|
||||
|
||||
The goal of this contract is to simulate economic cost of mining on a shorter branch.
|
||||
|
||||
1. With my signature I am certifying that I computed `state hash` at `PoH count tick count` and `PoH hash`.
|
||||
2. I will not vote on a branch that doesn't contain this message for at least `N` counts, or until `PoH tick count` + `N` is reached by the PoH stream (lockout period).
|
||||
3. I will not vote for any other branch below `PoH count`.
|
||||
a. if there are other votes not present in this PoH history the validator may need to `cancel` them before creating this vote.
|
||||
4. Each vote on a branch increases the lockout for all prior votes on that branch according to a network-specified function.
|
@ -1,55 +0,0 @@
|
||||
# Storage
|
||||
|
||||
The goal of this RFC is to define a protocol for storing a very large ledger over a p2p network that is verified by solana validators. At full capacity on a 1gbps network solana will generate 4 petabytes of data per year. To prevent the network from centralizing around full nodes that have to store the full data set this protocol proposes a way for mining nodes to provide storage capacity for pieces of the network.
|
||||
|
||||
# Version
|
||||
|
||||
version 0.1
|
||||
|
||||
# Background
|
||||
|
||||
The basic idea to Proof of Replication is encrypting a dataset with a public symmetric key using CBC encryption, then hash the encrypted dataset. The main problem with the naive approach is that a dishonest storage node can stream the encryption and delete the data as its hashed. The simple solution is to force the hash to be done on the reverse of the encryption, or perhaps with a random order. This ensures that all the data is present during the generation of the proof and it also requires the validator to have the entirety of the encrypted data present for verification of every proof of every identity. So the space required to validate is `(Number of Proofs)*(data size)`
|
||||
|
||||
# Optimization with PoH
|
||||
|
||||
Our improvement on this approach is to randomly sample the encrypted blocks faster than it takes to encrypt, and record the hash of those samples into the PoH ledger. Thus the blocks stay in the exact same order for every PoRep and verification can stream the data and verify all the proofs in a single batch. This way we can verify multiple proofs concurrently, each one on its own CUDA core. With the current generation of graphics cards our network can support up to 14k replication identities or symmetric keys. The total space required for verification is `(2 CBC blocks) * (Number of Identities)`, with core count of equal to (Number of Identities). A CBC block is expected to be 1MB in size.
|
||||
|
||||
# Network
|
||||
|
||||
Validators for PoRep are the same validators that are verifying transactions. They have some stake that they have put up as collateral that ensures that their work is honest. If you can prove that a validator verified a fake PoRep, then the validators stake can be slashed.
|
||||
|
||||
Replicators are specialized thin clients. They download a part of the ledger and store it, and provide PoReps of storing the ledger. For each verified PoRep replicators earn a reward of sol from the mining pool.
|
||||
|
||||
# Constraints
|
||||
|
||||
We have the following constraints:
|
||||
* At most 14k replication identities can be used, because thats how many CUDA cores we can fit in a $5k box at the moment.
|
||||
* Verification requires generating the CBC blocks. That requires space of 2 blocks per identity, and 1 CUDA core per identity for the same dataset. So as many identities at once should be batched with as many proofs for those identities verified concurrently for the same dataset.
|
||||
|
||||
# Validation and Replication Protocol
|
||||
|
||||
1. The network sets a replication target number, let's say 1k. 1k PoRep identities are created from signatures of a PoH hash. So they are tied to a specific PoH hash. It doesn't matter who creates them, or it could simply be the last 1k validation signatures we saw for the ledger at that count. This is maybe just the initial batch of identities, because we want to stagger identity rotation.
|
||||
2. Any client can use any of these identities to create PoRep proofs. Replicator identities are the CBC encryption keys.
|
||||
3. Periodically at a specific PoH count, a replicator that wants to create PoRep proofs signs the PoH hash at that count. That signature is the seed used to pick the block and identity to replicate. A block is 1TB of ledger.
|
||||
4. Periodically at a specific PoH count, a replicator submits PoRep proofs for their selected block. A signature of the PoH hash at that count is the seed used to sample the 1TB encrypted block, and hash it. This is done faster than it takes to encrypt the 1TB block with the original identity.
|
||||
5. Replicators must submit some number of fake proofs, which they can prove to be fake by providing the seed for the hash result.
|
||||
6. Periodically at a specific PoH count, validators sign the hash and use the signature to select the 1TB block that they need to validate. They batch all the identities and proofs and submit approval for all the verified ones.
|
||||
7. After #6, replicator client submit the proofs of fake proofs.
|
||||
|
||||
For any random seed, we force everyone to use a signature that is derived from a PoH hash. Everyone must use the same count, so the same PoH hash is signed by every participant. The signatures are then each cryptographically tied to the keypair, which prevents a leader from grinding on the resulting value for more than 1 identity.
|
||||
|
||||
We need to stagger the rotation of the identity keys. Once this gets going, the next identity could be generated by hashing itself with a PoH hash, or via some other process based on the validation signatures.
|
||||
|
||||
Since there are many more client identities then encryption identities, we need to split the reward for multiple clients, and prevent Sybil attacks from generating many clients to acquire the same block of data. To remain BFT we want to avoid a single human entity from storing all the replications of a single chunk of the ledger.
|
||||
|
||||
Our solution to this is to force the clients to continue using the same identity. If the first round is used to acquire the same block for many client identities, the second round for the same client identities will force a redistribution of the signatures, and therefore PoRep identities and blocks. Thus to get a reward for storage clients need to store the first block for free and the network can reward long lived client identities more than new ones.
|
||||
|
||||
# Notes
|
||||
|
||||
* We can reduce the costs of verification of PoRep by using PoH, and actually make it feasible to verify a large number of proofs for a global dataset.
|
||||
* We can eliminate grinding by forcing everyone to sign the same PoH hash and use the signatures as the seed
|
||||
* The game between validators and replicators is over random blocks and random encryption identities and random data samples. The goal of randomization is to prevent colluding groups from having overlap on data or validation.
|
||||
* Replicator clients fish for lazy validators by submitting fake proofs that they can prove are fake.
|
||||
* Replication identities are just symmetric encryption keys, the number of them on the network is our storage replication target. Many more client identities can exist than replicator identities, so unlimited number of clients can provide proofs of the same replicator identity.
|
||||
* To defend against Sybil client identities that try to store the same block we force the clients to store for multiple rounds before receiving a reward.
|
||||
* Validators should also get rewarded for validating submitted storage proofs as incentive for storing the ledger. They can only validate proofs if they are storing that slice of the ledger.
|
@ -1,108 +0,0 @@
|
||||
# Leader Rotation
|
||||
|
||||
The goal of this RFC is to define how leader nodes are rotated in Solana, how rotation may cause forks to arise, and how the converges
|
||||
in response.
|
||||
|
||||
## Version
|
||||
|
||||
version 0.1
|
||||
|
||||
## Leader Seed Generation
|
||||
|
||||
Leader selection is decided via a random seed. The process is as follows:
|
||||
|
||||
1. Periodically at a specific `PoH tick count` select the first vote signatures that create a supermajority from the previous voting round.
|
||||
2. Append them together.
|
||||
3. Hash the string for `N` counts via a similar process as PoH itself.
|
||||
4. The resulting hash is the random seed for `M` counts, `M` leader periods, where M > N
|
||||
|
||||
## Leader Rotation
|
||||
|
||||
1. The leader is chosen via a random seed generated from stake weights and votes (the leader schedule)
|
||||
2. The leader is rotated every `T` PoH ticks (leader period), accoding to the leader schedule
|
||||
3. The schedule is applicable for `M` voting rounds
|
||||
|
||||
Leader's transmit for a count of `T` PoH ticks. When `T` is reached all the validators should switch to the next scheduled leader. To schedule leaders, the supermajority + `M` nodes are shuffled using the above calculated random seed.
|
||||
|
||||
All `T` ticks must be observed from the current leader for that part of PoH to be accepted by the network. If `T` ticks (and any intervening transactions) are not observed, the network optimistically fills in the `T` ticks, and continues with PoH from the next leader.
|
||||
|
||||
## Partitions, Forks
|
||||
|
||||
Forks can arise at PoH tick counts that correspond to leader rotations, because leader nodes may or may not have observed the previous leader's data. These empty ticks are generated by all nodes in the network at a network-specified rate for hashes/per/tick `Z`.
|
||||
|
||||
There are only two possible versions of the PoH during a voting period: PoH with `T` ticks and entries generated by the current leader, or PoH with just ticks. The "just ticks" version of the PoH can be thought of as a virtual ledger, one that all nodes in the network can derive from the last tick in the previous period.
|
||||
|
||||
Validators can ignore forks at other points (e.g. from the wrong leader), or slash the leader responsible for the fork.
|
||||
|
||||
Validators vote on the longest chain that contains their previous vote, or a longer chain if the lockout on their previous vote has expired.
|
||||
|
||||
|
||||
#### Validator's View
|
||||
|
||||
##### Time Progression
|
||||
The diagram below represents a validator's view of the PoH stream with possible forks over time. L1, L2, etc. are leader periods, and `E`s represent entries from that leader during that leader's period. The 'x's represent ticks only, and time flows downwards in the diagram.
|
||||
|
||||
|
||||
```
|
||||
time +----+ validator action
|
||||
| | L1 | E(L1)
|
||||
| |----| / \ vote(E(L2))
|
||||
| | L2 | E(L2) x
|
||||
| |----| / \ / \ vote(E(L2))
|
||||
| | L3 | E(L3) x E(L3)' x
|
||||
| |----| / \ / \ / \ / \ slash(L3)
|
||||
| | L4 | x x E(L4) x x x x x
|
||||
V |----| | | | | | | | | vote(E(L4))
|
||||
V | L5 | xx xx xx E(L5) xx xx xx xx
|
||||
V +----+ hang on to E(L4) and E(L5) for more...
|
||||
|
||||
```
|
||||
|
||||
Note that an `E` appearing on 2 branches at the same period is a slashable condition, so a validator observing `E(L3)` and `E(L3)'` can slash L3 and safely choose `x` for that period. Once a validator observes a supermajority vote on any branch, other branches can be discarded below that tick count. For any period, validators need only consider a single "has entries" chain or a "ticks only" chain.
|
||||
|
||||
##### Time Division
|
||||
|
||||
It's useful to consider leader rotation over PoH tick count as time division of the job of encoding state for the network. The following table presents the above tree of forks as a time-divided ledger.
|
||||
|
||||
leader period | L1 | L2 | L3 | L4 | L5
|
||||
-------|----|----|----|----|----
|
||||
data | E(L1)| E(L2) | E(L3) | E(L4) | E(L5)
|
||||
ticks to prev | | | | x | xx
|
||||
|
||||
Note that only data from leader L3 will be accepted during leader period L3. Data from L3 may include "catchup" ticks back to a period other than L2 if L3 did not observe L2's data. L4 and L5's transmissions include the "ticks to prev" PoH entries.
|
||||
|
||||
This arrangement of the network data streams permits nodes to save exactly this to the ledger for replay, restart, and checkpoints.
|
||||
|
||||
#### Leader's View
|
||||
|
||||
When a new leader begins a period, it must first transmit any PoH (ticks) required to link the new period with the most recently observed and voted period.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Small Partition
|
||||
1. Network partition M occurs for 10% of the nodes
|
||||
2. The larger partition K, with 90% of the stake weight continues to operate as normal
|
||||
3. M cycles through the ranks until one of them is leader, generating ticks for periods where the leader is in K.
|
||||
4. M validators observe 10% of the vote pool, finality is not reached.
|
||||
5. M and K re-connect.
|
||||
6. M validators cancel their votes on M, which has not reached finality, and re-cast on K (after their vote lockout on M).
|
||||
|
||||
### Leader Timeout
|
||||
1. Next rank leader node V observes a timeout from current leader A, fills in A's period with virtual ticks and starts sending out entries.
|
||||
2. Nodes observing both streams keep track of the forks, waiting for:
|
||||
a. their vote on leader A to expire in order to be able to vote on B
|
||||
b. a supermajority on A's period
|
||||
3. If a occurs, leader B's period is filled with ticks, if b occurs, A's period is filled with ticks
|
||||
4. Partition is resolved just like in the [Small Partition](#small-parition)
|
||||
|
||||
|
||||
## Network Variables
|
||||
|
||||
`M` - number of nodes outside the supermajority to whom leaders broadcast their PoH for validation
|
||||
|
||||
`N` - number of voting rounds for which a leader schedule is considered before a new leader schedule is used
|
||||
|
||||
`T` - number of PoH ticks per leader period (also voting period)
|
||||
|
||||
`Z` - number of hashes per PoH tick
|
@ -1,59 +0,0 @@
|
||||
```
|
||||
========================= master branch (edge channel) =======================>
|
||||
\ \ \
|
||||
\___v0.7.0 tag \ \
|
||||
\ \ v0.9.0 tag__\
|
||||
\ v0.8.0 tag__\ \
|
||||
v0.7.1 tag__\ \ v0.9 branch (beta channel)
|
||||
\___v0.7.2 tag \___v0.8.1 tag
|
||||
\ \
|
||||
\ \
|
||||
v0.7 branch v0.8 branch (stable channel)
|
||||
|
||||
```
|
||||
|
||||
## Branches and Tags
|
||||
|
||||
### master branch
|
||||
All new development occurs on the `master` branch.
|
||||
|
||||
Bug fixes that affect a `vX.Y` branch are first made on `master`. This is to
|
||||
allow a fix some soak time on `master` before it is applied to one or more
|
||||
stabilization branches.
|
||||
|
||||
Merging to `master` first also helps ensure that fixes applied to one release
|
||||
are present for future releases. (Sometimes the joy of landing a critical
|
||||
release blocker in a branch causes you to forget to propagate back to
|
||||
`master`!)"
|
||||
|
||||
Once the bug fix lands on `master` it is cherry-picked into the `vX.Y` branch
|
||||
and potentially the `vX.Y-1` branch. The exception to this rule is when a bug
|
||||
fix for `vX.Y` doesn't apply to `master` or `vX.Y-1`.
|
||||
|
||||
Immediately after a new stabilization branch is forged, the `Cargo.toml` minor
|
||||
version (*Y*) in the `master` branch is incremented by the release engineer.
|
||||
Incrementing the major version of the `master` branch is outside the scope of
|
||||
this document.
|
||||
|
||||
### v*X.Y* stabilization branches
|
||||
These are stabilization branches for a given milestone. They are created off
|
||||
the `master` branch as late as possible prior to the milestone release.
|
||||
|
||||
### v*X.Y.Z* release tag
|
||||
The release tags are created as desired by the owner of the given stabilization
|
||||
branch, and cause that *X.Y.Z* release to be shipped to https://crates.io,
|
||||
https://snapcraft.io/, and elsewhere.
|
||||
|
||||
Immediately after a new v*X.Y.Z* branch tag has been created, the `Cargo.toml`
|
||||
patch version number (*Z*) of the stabilization branch is incremented by the
|
||||
release engineer.
|
||||
|
||||
## Channels
|
||||
Channels are used by end-users (humans and bots) to consume the branches
|
||||
described in the previous section, so they may automatically update to the most
|
||||
recent version matching their desired stability.
|
||||
|
||||
There are three release channels that map to branches as follows:
|
||||
* edge - tracks the `master` branch, least stable.
|
||||
* beta - tracks the largest (and latest) `vX.Y` stabilization branch, more stable.
|
||||
* stable - tracks the second largest `vX.Y` stabilization branch, most stable.
|
@ -1,124 +0,0 @@
|
||||
|
||||
### Wallet CLI
|
||||
|
||||
The general form is:
|
||||
```
|
||||
$ solana-wallet [common-options] [command] [command-specific options]
|
||||
```
|
||||
`common-options` include:
|
||||
* `--fee xyz` - Transaction fee (0 by default)
|
||||
* `--output file` - Write the raw Transaction to a file instead of sending it
|
||||
|
||||
`command` variants:
|
||||
* `pay`
|
||||
* `cancel`
|
||||
* `send-signature`
|
||||
* `send-timestamp`
|
||||
|
||||
#### Unconditional Immediate Transfer
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet pay <PUBKEY> 123
|
||||
|
||||
// Return
|
||||
<TX_SIGNATURE>
|
||||
```
|
||||
|
||||
#### Post-Dated Transfer
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet pay <PUBKEY> 123 \
|
||||
--after 2018-12-24T23:59:00 --require-timestamp-from <PUBKEY>
|
||||
|
||||
// Return
|
||||
{signature: <TX_SIGNATURE>, processId: <PROCESS_ID>}
|
||||
```
|
||||
*`require-timestamp-from` is optional. If not provided, the transaction will expect a timestamp signed by this wallet's secret key*
|
||||
|
||||
#### Authorized Transfer
|
||||
A third party must send a signature to unlock the tokens.
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet pay <PUBKEY> 123 \
|
||||
--require-signature-from <PUBKEY>
|
||||
|
||||
// Return
|
||||
{signature: <TX_SIGNATURE>, processId: <PROCESS_ID>}
|
||||
```
|
||||
|
||||
#### Post-Dated and Authorized Transfer
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet pay <PUBKEY> 123 \
|
||||
--after 2018-12-24T23:59 --require-timestamp-from <PUBKEY> \
|
||||
--require-signature-from <PUBKEY>
|
||||
|
||||
// Return
|
||||
{signature: <TX_SIGNATURE>, processId: <PROCESS_ID>}
|
||||
```
|
||||
|
||||
#### Multiple Witnesses
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet pay <PUBKEY> 123 \
|
||||
--require-signature-from <PUBKEY> \
|
||||
--require-signature-from <PUBKEY>
|
||||
|
||||
// Return
|
||||
{signature: <TX_SIGNATURE>, processId: <PROCESS_ID>}
|
||||
```
|
||||
|
||||
#### Cancelable Transfer
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet pay <PUBKEY> 123 \
|
||||
--require-signature-from <PUBKEY> \
|
||||
--cancelable
|
||||
|
||||
// Return
|
||||
{signature: <TX_SIGNATURE>, processId: <PROCESS_ID>}
|
||||
```
|
||||
|
||||
#### Cancel Transfer
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet cancel <PROCESS_ID>
|
||||
|
||||
// Return
|
||||
<TX_SIGNATURE>
|
||||
```
|
||||
|
||||
#### Send Signature
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet send-signature <PUBKEY> <PROCESS_ID>
|
||||
|
||||
// Return
|
||||
<TX_SIGNATURE>
|
||||
```
|
||||
|
||||
#### Indicate Elapsed Time
|
||||
|
||||
Use the current system time:
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet send-timestamp <PUBKEY> <PROCESS_ID>
|
||||
|
||||
// Return
|
||||
<TX_SIGNATURE>
|
||||
```
|
||||
|
||||
Or specify some other arbitrary timestamp:
|
||||
```sh
|
||||
// Command
|
||||
$ solana-wallet send-timestamp <PUBKEY> <PROCESS_ID> --date 2018-12-24T23:59:00
|
||||
|
||||
// Return
|
||||
<TX_SIGNATURE>
|
||||
```
|
||||
|
||||
|
||||
## Javascript solana-web3.js Interface
|
||||
|
||||
*TBD, but will look similar to what the Wallet CLI offers wrapped up in a
|
||||
Javacsript object*
|
Reference in New Issue
Block a user