mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
book: Remove DNA, add payment transaction stub.
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
- [Blockchain](architecture/blockchain.md)
|
||||
- [Consensus](architecture/consensus.md)
|
||||
- [Transactions](architecture/tx_lifetime.md)
|
||||
- [DNA](architecture/dna.md)
|
||||
- [Smart Contracts](architecture/smart_contracts.md)
|
||||
- [Tooling](architecture/tooling.md)
|
||||
- [Client](clients/clients.md)
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
DarkFi Node Architecture (DNA)
|
||||
==============================
|
||||
|
||||
The DarkFi ecosystem runs as a network of P2P nodes, where these nodes
|
||||
interact with each other over specific programs (or layers). In this
|
||||
section, we'll explain how each of the layers fit together and when
|
||||
combined create a functioning network that becomes DarkFi.
|
||||
|
||||
The layers are organized as a bottom-up pyramid, much like the
|
||||
DarkFi logo:
|
||||
|
||||
$$ \setminus validatord / $$
|
||||
$$ \setminus darkfid / $$
|
||||
$$ \setminus drk / $$
|
||||
|
||||
We will start with the top-level daemon - `validatord` - which
|
||||
serves as the consensus and data storage layer, then we will explain
|
||||
`darkfid` and its communication with the layer above (`validatord`),
|
||||
and the layer below (`drk`).
|
||||
|
||||
An abstract view of the network looks like the following:
|
||||
|
||||
```
|
||||
[drk] <--> [darkfid] <--> [validatord] <-+
|
||||
|
|
||||
[drk] <--> [darkfid] <--> [validatord] <-+
|
||||
```
|
||||
|
||||
|
||||
## validatord
|
||||
|
||||
`validatord` is the DarkFi consensus and data storage layer. Everyone
|
||||
that runs a validator participates in the network as a data archive,
|
||||
and is able to store incoming transactions, and relay them to
|
||||
other validators over the P2P network and protocol. Additionally,
|
||||
storing this data allows others to replicate it and participate in
|
||||
the same way.
|
||||
|
||||
Provided there is a locked stake on a running validator, the node
|
||||
can also participate in the Proof-of-Stake consensus, enabling the
|
||||
ability to vote on incoming transactions rather than just relaying
|
||||
(and validating) them.
|
||||
|
||||
In case the node is not participating in the consensus, it should still
|
||||
relay incoming transactions to other (ideally consensus-participating)
|
||||
validators in the network.
|
||||
|
||||
### Inner workings
|
||||
|
||||
In its database, `validatord` stores transactions and blocks that
|
||||
have reached consensus. This is commonly known as a _"blockchain"_.
|
||||
The blockchain is a shared state that is replicated between all
|
||||
validators in the network.
|
||||
|
||||
Additionally, validators keep a pool of incoming transactions
|
||||
and proposed blocks, which get validated and voted on by the
|
||||
consensus-participating validators.
|
||||
|
||||
The lifetime of an incoming transaction (and block) is as follows:
|
||||
|
||||
1. Wait for a transaction
|
||||
2. Validate incoming transaction (and go back to 1. if invalid)
|
||||
3. Broadcast transaction to other validators in the network
|
||||
4. Other validators validate transaction (and go back to 1. if invalid)
|
||||
5. Leader validates the state transition and proposes a block
|
||||
6. Consensus-participating nodes validate the state transition and
|
||||
vote on the proposed block if the state transition is valid.
|
||||
7. If the block is confirmed, it is appended to the _blockchain_ and
|
||||
is replicated between all validators in the network.
|
||||
|
||||
|
||||
## darkfid
|
||||
|
||||
`TODO: Initial sync and retrieving wallet state?`
|
||||
|
||||
`darkfid` is the client layer of DarkFi used for wallet management
|
||||
and transaction broadcasting. The wallet keeps a history of balances,
|
||||
_coins_, _nullifiers_, and _merkle roots_ that are necessary in order
|
||||
to create new transactions.
|
||||
|
||||
By design, `darkfid` is a light client, since `validatord` stores all
|
||||
the blockchain data, and `darkfid` can simply query for anything it
|
||||
is interested in. This allows us to avoid data duplication and simply
|
||||
utilize our modular architecture. This also means that `darkfid` can
|
||||
easily be replaced with more specific tooling, if need be.
|
||||
|
||||
### Inner workings
|
||||
|
||||
Using the P2P network and protocol, `darkfid` can subscribe to
|
||||
`validatord` in order to receive new _nullifiers_ and _merkle roots_
|
||||
whenever a new block is confirmed. This allows `darkfid` to update
|
||||
its local state and enables it to create new valid transactions.
|
||||
|
||||
`darkfid` exposes a JSON-RPC endpoint for clients to interact with it.
|
||||
This allows a number of things, such as: listing balances, creating
|
||||
and submitting transactions, key management, and more.
|
||||
|
||||
When creating a new transactions, `darkfid` uses the local synced state
|
||||
in order to create new _coins_ and combine them in a transaction. This
|
||||
transaction is then submitted to the above validator layer where the
|
||||
transaction will get validated and voted on in order to be included
|
||||
into a block.
|
||||
|
||||
|
||||
## drk
|
||||
|
||||
`drk` is a client tool that interacts with `darkfid` in a user-friendly
|
||||
way and provides a command-line interface to the DarkFi network and
|
||||
its functionality.
|
||||
|
||||
The interaction with `darkfid` is done over the JSON-RPC protocol
|
||||
and communicates with the endpoint exposed by `darkfid`.
|
||||
@@ -1,7 +1,9 @@
|
||||
# Transaction behaviour
|
||||
# Transactions
|
||||
|
||||
_(Temporary document, to be integrated into other docs)_
|
||||
|
||||
## Transaction behaviour
|
||||
|
||||
In our network context, we have two types of nodes.
|
||||
|
||||
1. Consensus Participant (`CP`)
|
||||
@@ -96,3 +98,99 @@ for any fork(including canonical) or it get finalized.
|
||||
Unproposed transactions refers to all $tx$ not included in a proposal of any fork.
|
||||
|
||||
If a fork that can be finalized fails to validate all its transactions(14), it should be dropped.
|
||||
|
||||
## The `Transaction` object
|
||||
|
||||
```rust
|
||||
pub struct ContractCall {
|
||||
/// The contract ID to which the payload is fed to
|
||||
pub contract_id: ContractId,
|
||||
/// Arbitrary payload for the contract call
|
||||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct Transaction {
|
||||
/// Calls executed in this transaction
|
||||
pub calls: Vec<ContractCall>,
|
||||
/// Attached ZK proofs
|
||||
pub proofs: Vec<Vec<Proof>>,
|
||||
/// Attached Schnorr signatures
|
||||
pub signatures: Vec<Vec<Signature>>,
|
||||
}
|
||||
```
|
||||
|
||||
A generic DarkFi transaction object is simply an array of smart
|
||||
contract calls, along with attached ZK proofs and signatures needed
|
||||
to properly verify the contracts' execution. A transaction can have
|
||||
any number of calls, and proofs, provided it does not exhaust a set
|
||||
gas limit.
|
||||
|
||||
In DarkFi, every operation is a smart contract. This includes payments,
|
||||
which we'll explain in the following section.
|
||||
|
||||
## Payments
|
||||
|
||||
For A -> B payments in DarkFi we use the Sapling scheme that originates
|
||||
from zcash. A payment transaction has a number of _inputs_ (which are
|
||||
coins being burned/spent), and a number of _outputs_ (which are coins
|
||||
being minted/created). An explanation for the ZK proofs for this scheme
|
||||
can be found in the Zkas section of this book, under Sapling.
|
||||
|
||||
In code, the structs we use are the following:
|
||||
|
||||
```rust
|
||||
pub struct MoneyTransferParams {
|
||||
pub inputs: Vec<Input>,
|
||||
pub outputs: Vec<Output>,
|
||||
}
|
||||
|
||||
pub struct Input {
|
||||
/// Pedersen commitment for the input's value
|
||||
pub value_commit: ValueCommit,
|
||||
/// Pedersen commitment for the input's token ID
|
||||
pub token_commit: ValueCommit,
|
||||
/// Revealed nullifier
|
||||
pub nullifier: Nullifier,
|
||||
/// Revealed Merkle root
|
||||
pub merkle_root: MerkleNode,
|
||||
/// Public key for the Schnorr signature
|
||||
pub signature_public: PublicKey,
|
||||
}
|
||||
|
||||
pub struct Output {
|
||||
/// Pedersen commitment for the output's value
|
||||
pub value_commit: ValueCommit,
|
||||
/// Pedersen commitment for the output's token ID
|
||||
pub token_commit: ValueCommit,
|
||||
/// Minted coin: poseidon_hash(pubkey, value, token, serial, blind)
|
||||
pub coin: Coin,
|
||||
/// The encrypted note ciphertext
|
||||
pub encrypted_note: EncryptedNote,
|
||||
}
|
||||
|
||||
pub struct EncryptedNote {
|
||||
pub ciphertext: Vec<u8>,
|
||||
pub ephemeral_key: PublicKey,
|
||||
}
|
||||
|
||||
pub struct Note {
|
||||
/// Serial number of the coin, used to derive the nullifier
|
||||
pub serial: pallas::Base,
|
||||
/// Value of the coin
|
||||
pub value: u64,
|
||||
/// Token ID of the coin
|
||||
pub token_id: TokenId,
|
||||
/// Blinding factor for the coin bulla
|
||||
pub coin_blind: pallas::Base,
|
||||
/// Blinding factor for the value Pedersen commitment
|
||||
pub value_blind: ValueBlind,
|
||||
/// Blinding factor for the token ID Pedersen commitment
|
||||
pub token_blind: ValueBlind,
|
||||
/// Attached memo (arbitrary data)
|
||||
pub memo: Vec<u8>,
|
||||
}
|
||||
```
|
||||
|
||||
In the blockchain state, every minted coin must be added into a Merkle
|
||||
tree of all existing coins. Once added, the new tree root is used to
|
||||
prove existence of this coin when it's being spent.
|
||||
|
||||
Reference in New Issue
Block a user