Document the processor/tributary/coordinator/serai flow

This commit is contained in:
Luke Parker 2023-04-25 15:05:58 -04:00
parent 78d5372fb7
commit 7824b6cb8b
No known key found for this signature in database
5 changed files with 256 additions and 5 deletions

View file

@ -393,11 +393,11 @@ pub async fn handle_processors<D: Db, Pro: Processor, P: P2p>(
let tributaries = tributaries.read().await;
let Some(tributary) = tributaries.get(&genesis) else {
// TODO: This can happen since Substrate tells the Processor to generate commitments
// at the same time it tells the Tributary to be created
// There's no guarantee the Tributary will have been created though
panic!("processor is operating on tributary we don't have");
};
// TODO: This can happen since Substrate tells the Processor to generate commitments
// at the same time it tells the Tributary to be created
// There's no guarantee the Tributary will have been created though
panic!("processor is operating on tributary we don't have");
};
let tributary = tributary.tributary.read().await;
if tributary

View file

@ -99,6 +99,8 @@ async fn handle_block<D: Db, Pro: Processor>(
// TODO: We can also full slash if shares before all commitments, or share before the
// necessary preprocesses
// TODO: If this is shares, we need to check they are part of the selected signing set
// Store this data
let received =
TributaryDb::<D>::set_data(label, &mut txn, genesis, id, attempt, signed.signer, &bytes);

View file

@ -0,0 +1,40 @@
# Coordinator
The coordinator is a service which communicates with all of the processors,
all of the other coordinators over a secondary P2P network, and with the Serai
node.
This document primarily details its flow with regards to the Serai node and
processor.
## New Set Event
On `validator_sets::pallet::Event::NewSet`, the coordinator spawns a tributary
for the new set. It additionally sends the processor
`key_gen::CoordinatorMessage::GenerateKey`.
## Generated Key Pair
On `key_gen::ProcessorMessage::GeneratedKeyPair`, a
`validator_sets::pallet::vote` transaction is made to vote in the new key.
The Serai blockchain needs to know the key pair in order for it to be able to
publish `Batch`s. Additionally, having the Serai blockchain confirm the keys
provides a BFT consensus guarantee. While the tributary itself could also offer
a BFT consensus guarantee, there's no point when we'd then get BFT consensus
on the Serai blockchain anyways.
## Key Generation Event
On `validator_sets::pallet::Event::KeyGen`, the coordinator sends
`substrate::CoordinatorMessage::ConfirmKeyPair` to the processor.
# Update
On `key_gen::ProcessorMessage::Update`, the coordinator publishes an unsigned
transaction containing the signed batch to the Serai blockchain.
# Sign Completed
On `sign::ProcessorMessage::Completed`, the coordinator broadcasts the
contained information to all validators.

View file

@ -0,0 +1,91 @@
# Tributary
A tributary is a side-chain, created for a specific multisig instance, used
as a verifiable broadcast layer.
## Transactions
### Key Gen Commitments
`DkgCommitments` is created when a processor sends the coordinator
`key_gen::ProcessorMessage::Commitments`. When all validators participating in
a multisig publish `DkgCommitments`, the coordinator sends the processor
`key_gen::CoordinatorMessage::Commitments`.
### Key Gen Shares
`DkgShares` is created when a processor sends the coordinator
`key_gen::ProcessorMessage::Shares`. When all validators participating in
a multisig publish `DkgShares`, the coordinator sends the processor
`key_gen::CoordinatorMessage::Shares`.
### External Block
When *TODO*, a `ExternalBlock` transaction is provided. This is used to have
the group acknowledge and synchronize around the block, without the overhead of
voting in its acknowledgment.
When a `ExternalBlock` transaction is included, participants are allowed to
publish transactions to produce a threshold signature for the block's `Batch`.
### Substrate Block
`SubstrateBlock` is provided when the processor sends the coordinator
`substrate::ProcessorMessage::SubstrateBlockAck`.
When a `SubstrateBlock` transaction is included, participants are allowed to
publish transactions for the signing protocols it causes.
### Batch Preprocess
`BatchPreprocess` is created when a processor sends the coordinator
`coordinator::ProcessorMessage::BatchPreprocess` and an `ExternalBlock`
transaction allowing the batch to be signed has already been included on chain.
When `t` validators have published `BatchPreprocess` transactions, a
`coordinator::ProcessorMessage::BatchPreprocesses` is sent to the processor.
### Batch Share
`BatchShare` is created when a processor sends the coordinator
`coordinator::ProcessorMessage::BatchShare`. The relevant `ExternalBlock`
transaction having already been included on chain follows from
`coordinator::ProcessorMessage::BatchShare` being a response to a message which
also has that precondition.
When the `t` validators who first published `BatchPreprocess` transactions have
published `BatchShare` transactions, a
`coordinator::ProcessorMessage::BatchShares` with the relevant shares is sent
to the processor.
### Sign Preprocess
`SignPreprocess` is created when a processor sends the coordinator
`sign::ProcessorMessage::Preprocess` and a `SubstrateBlock` transaction
allowing the transaction to be signed has already been included on chain.
When `t` validators have published `SignPreprocess` transactions, a
`sign::ProcessorMessage::Preprocesses` is sent to the processor.
### Sign Share
`SignShare` is created when a processor sends the coordinator
`sign::ProcessorMessage::Share`. The relevant `SubstrateBlock` transaction
having already been included on chain follows from
`sign::ProcessorMessage::Share` being a response to a message which
also has that precondition.
When the `t` validators who first published `SignPreprocess` transactions have
published `SignShare` transactions, a `sign::ProcessorMessage::Shares` with the
relevant shares is sent to the processor.
## Re-attempts
The key generation and signing protocols, whether batch or transaction, may
fail if a validator goes offline or takes too long to respond. Accordingly,
the tributary will schedule re-attempts. These are communicated with
`key_gen::CoordinatorMessage::GenerateKey`,
`coordinator::CoordinatorMessage::BatchReattempt`, and
`sign::CoordinatorMessage::Reattempt`.
TODO: Document the re-attempt scheduling logic.

118
docs/processor/Processor.md Normal file
View file

@ -0,0 +1,118 @@
# Processor
The processor is a service which has an instance spawned per network. It is
responsible for several tasks, from scanning the connected network to signing
transactions with payments.
This document primarily discusses its flow with regards to the coordinator.
## Generate Key
On `key_gen::CoordinatorMessage::GenerateKey`, the processor begins a pair of
instances of the distributed key generation protocol specified in the FROST
paper.
The first instance is for a key to use on the connected network. The second
instance is for a Ristretto public key used to publish data to the Serai
blockchain. This pair of FROST DKG instances is considered a single instance of
Serai's overall key generation protocol.
The commitments for both protocols are sent to the coordinator in a single
`key_gen::ProcessorMessage::Commitments`.
## Key Gen Commitments
On `key_gen::CoordinatorMessage::Commitments`, the processor continues the
specified key generation instance. The secret shares for each fellow
participant are sent to the coordinator in a
`key_gen::ProcessorMessage::Shares`.
### Key Gen Shares
On `key_gen::CoordinatorMessage::Shares`, the processor completes the specified
key generation instance. The generated key pair is sent to the coordinator in a
`key_gen::ProcessorMessage::GeneratedKeyPair`.
## Confirm Key Pair
On `substrate::CoordinatorMessage::ConfirmKeyPair`, the processor starts using
the newly confirmed key, scanning blocks on the connected network for
transfers to it.
## Connected Network Block
When the connected network has a new block, which is considered finalized
(either due to being literally finalized or due to having a sufficient amount
of confirmations), it's scanned.
Outputs to the key of Serai's multisig are saved to the database. Outputs which
newly transfer into Serai are used to build a `Batch` for the block. The
processor then begins a threshold signature protocol with its key pair's
Ristretto key to sign the batch. The protocol's preprocess is sent to the
coordinator in a `coordinator::ProcessorMessage::BatchPreprocess`.
As a design comment, we *may* be able to sign now possible, already scheduled,
branch/leaf transactions at this point. Doing so would be giving a mutable
borrow over the scheduler to both the external network and the Serai network,
and would accordingly be unsafe. We may want to look at splitting the scheduler
in two, in order to reduce latency (TODO).
## Batch Preprocesses
On `coordinator::CoordinatorMessage::BatchPreprocesses`, the processor
continues the specified batch signing protocol, sending
`coordinator::ProcessorMessage::BatchShare` to the coordinator.
## Batch Shares
On `coordinator::CoordinatorMessage::BatchShares`, the processor
completes the specified batch signing protocol. If successful, the processor
stops signing for this batch and sends `substrate::ProcessorMessage::Update` to
the coordinator.
## Batch Re-attempt
On `coordinator::CoordinatorMessage::BatchReattempt`, the processor will create
a new instance of the batch signing protocol. The new protocol's preprocess is
sent to the coordinator in a `coordinator::ProcessorMessage::BatchPreprocess`.
## Substrate Block
On `substrate::CoordinatorMessage::SubstrateBlock`, the processor:
1) Marks all blocks, up to the external block now considered finalized by
Serai, as having had their batches signed.
2) Adds the new outputs from newly finalized blocks to the scheduler, along
with the necessary payments from `Burn` events on Serai.
The processor also sends a `substrate::ProcessorMessage::SubstrateBlockAck`,
containing the IDs of all plans now being signed for, to the coordinator.
## Sign Preprocesses
On `sign::CoordinatorMessage::Preprocesses`, the processor continues the
specified transaction signing protocol, sending `sign::ProcessorMessage::Share`
to the coordinator.
## Sign Shares
On `sign::CoordinatorMessage::Shares`, the processor completes the specified
transaction signing protocol. If successful, the processor stops signing for
this transaction and publishes the signed transaction. Then,
`sign::ProcessorMessage::Completed` is sent to the coordinator, to be
broadcasted to all validators so everyone can observe the transaction was
signed and stop locally attempting to do so.
## Sign Re-attempt
On `sign::CoordinatorMessage::Reattempt`, the processor will create a new
a new instance of the transaction signing protocol. The new protocol's
preprocess is sent to the coordinator in a
`sign::ProcessorMessage::Preprocess`.
## Sign Completed
On `sign::CoordinatorMessage::Completed`, the processor verifies the included
transaction hash actually refers to an accepted transaction which completes the
plan it was supposed to. If so, the processor stops locally signing for the
transaction, and emits `sign::ProcessorMessage::Completed`.