Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add rfc 321 #112

Merged
merged 27 commits into from
Dec 22, 2023
Merged
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5513136
feat: add rfc 321
stringhandler Nov 20, 2023
0c90375
review suggestions
stringhandler Nov 21, 2023
17487d7
ci(fix): prevent code injection (#114)
leet4tari Dec 5, 2023
296f587
feat: layer 2 specification (#111)
CjS77 Dec 5, 2023
7d23333
chore: edits and numbering fix (#115)
CjS77 Dec 5, 2023
845e7e5
docs: update documentation for `ToRistrettoPoint` opcode (#113)
AaronFeickert Dec 6, 2023
9974547
feat: cerberus detail (#118)
CjS77 Dec 17, 2023
51e851a
chore: add epoch management to summary (#116)
CjS77 Dec 18, 2023
16c6f36
fix: remove old maintainers (#119)
CjS77 Dec 18, 2023
02b1354
feat: stablecoin draft specification (#107)
CjS77 Dec 19, 2023
830d543
fix: stablecoin rfc title (#120)
CjS77 Dec 19, 2023
50773a7
fix: typos and small fixes (#121)
AaronFeickert Dec 19, 2023
c6186a9
fix: upgrade mdbook (#123)
CjS77 Dec 19, 2023
ce7ce10
Upgrade mdbook (#124)
CjS77 Dec 19, 2023
56ac765
fix: upgrade mdbook-mermaid (#126)
CjS77 Dec 19, 2023
aa31b02
fix: remove old mermaid version (#125)
CjS77 Dec 19, 2023
9e59acc
fix: fix mermaid again (#127)
CjS77 Dec 19, 2023
8c3d10f
feat: update content for rfc-331 (#128)
CjS77 Dec 20, 2023
95e6881
feat: Tari logic layer
CjS77 Dec 19, 2023
33cd968
chore: update change log table in template
CjS77 Dec 20, 2023
73a0653
fix: make ci compatible with local build
CjS77 Dec 20, 2023
542c6b5
updates
stringhandler Dec 22, 2023
14fed39
feat: add rfc 321
stringhandler Nov 20, 2023
d8cf077
review suggestions
stringhandler Nov 21, 2023
3878378
updates
stringhandler Dec 22, 2023
13344f4
add to summary
stringhandler Dec 22, 2023
2add2da
Merge branch 'st-rfc-processing-foreign-proposals' of github.com:tari…
stringhandler Dec 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions src/RFC-0321_ProcessingForeignProposals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# RFC-0321/ProcessingForeignProposals

## Processing Foreign Proposals

![status: draft](theme/images/status-draft.svg)

**Maintainer(s)**: [stringhandler](https://github.com/stringhandler)

# Licence

[The 3-Clause BSD Licence](https://opensource.org/licenses/BSD-3-Clause).

Copyright 2022 The Tari Development Community

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:

1. Redistributions of this document must retain the above copyright notice, this list of conditions and the following
disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS DOCUMENT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

## Language

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",
"NOT RECOMMENDED", "MAY" and "OPTIONAL" in this document are to be interpreted as described in
[BCP 14](https://tools.ietf.org/html/bcp14) (covering RFC2119 and RFC8174) when, and only when, they appear in all capitals, as
shown here.

## Disclaimer

This document and its content are intended for information purposes only and may be subject to change or update
without notice.

This document may include preliminary concepts that may or may not be in the process of being developed by the Tari
community. The release of this document is intended solely for review and discussion by the community of the
technological merits of the potential system outlined herein.

## Goals

This RFC describes the process of distributing and processing foreign proposals in the Tari DAN Cerberus Model

Across the entire network transactions must be processed or time out. When a transaction is started on a shard, it locks up substates, preventing other transactions from completing. Therefore if a transaction is started on a shard, it
should complete or be aborted in a timely manner to release the resources.

## Related Requests for Comment

<!-- * [RFC-0111: Base Node Architecture](./RFC-0111_BaseNodeArchitecture.md) -->
None

## Glossary

* Block - A second layer block, consisting of ordered commands
* Command - Command can either be Prepare, LocalPrepared, Accept, and moves a transaction into that state.

## Description

To solve the above problems, we'll use reliable broadcast and process foreign evidence in order.

In a local shard committee, the proposed block **must** include a counter per epoch and per shard (except for the local shard). If the proposal includes transactions that involve other shards, this counter **must** be incremented.

When the proposed block becomes committed locally, the block **must** be broadcast to each involved shard that was incremented, along with evidence of being committeed (The chain of QCs must be included).

To ensure this, each node in the local committee will forward this committed block, along with a 3 chain of QC's proving it was committeed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, if you send only 3 QCs you can't prove they are actually from one 3 chain. You can prove that you have a QC1 on top of the fLP block. But you can't prove that you have a QC2 on top of the block with QC1.
Maybe we should add block.justify() not just block_id to the QC. But I'm hope that we can come up with a better solution.


As a local committee member, when I receive a foreign proposal, if it is valid I will queue up a special command ForeignProposal(number, QC_Hash) that I must propose
when I am next leader (if it has not been proposed already). I also **should** request all transaction hashes that I have not seen from involved_shards for each transaction in the proposal, and add them to my mempool for execution.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just for notifying the rest of the committee that they should be aware of the foreign proposal? They will need it anyway when they will try to validate TX going from local_prepared to accept. Voting on this special command is the same as voting on individual transactions that includes foreign shards. Or am I missing something?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason is to set a starting point for a timeout. If the ForeignProposal command is committed, then 2f+1 nodes have agreed that this data has arrived and all of them will try to retrieve the transaction. If the transaction does exist, then at least one of them should find it and be able to propose it, if none of the nodes can find it in that time, the transaction must timeout.

Copy link
Contributor

@Cifko Cifko Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was expecting that the timer starts once I send something to the foreign committees and I expect an answer. E.g. I send Prepare(tx)/LocalPrepare to foreign committee, I start a timer that I'm expecting to receive something.
Maybe I'm misunderstanding what is the timer waiting for.
If I understand that correctly. The current approach is that I send something to foreign committee and I expect that committee to start a timer and if they are not able to process the Tx, after the timeout they will send a timeout proposal to me. That sounds more complicated than starting a timer once I send to foreign committee something and I wait for response. Because I'll not rely on the foreign committee to process it. I will just time it out myself.

Copy link
Member

@sdbondi sdbondi Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify: if a node receives ForeignProposal(tx_1) and doesn't know tx_1, it will request it from the local nodes?

It may not be necessary to have an explicit command to indicate receipt of foreign LocalPrepared because All/SomePrepared (a.k.a Accept?) already implies that. But we may need a way to indicate that the foreign LocalPrepared at the All/SomePrepared level was never received to get finality on all transactions.

Let's say we have these commands:
Prepare(P) -> LocalPrepare(LP) -> AllPrepare(AP)|SomePrepare(SP)|Timeout(T) ->Finalize(F)

and these statuses:
COMMIT, ABORT, TIMEOUT

Formatting "tx atoms" as {Command}({tx_id}, {status:=COMMIT|ABORT|TIMEOUT) e.g. LocalPrepare(tx_1, COMMIT). fp(LP, tx_1, COMMIT) = foreign proposal for LocalPrepare to COMMIT tx_1

Case Local knows tx_1 Received foreign LP
A Yes Yes
B Not yet Yes
C Never Yes
D Yes Not yet
E Yes Never

Case A: The "normal" case. Prepare -> LocalPrepare ->(send) -> AllPrepare->(send) ->Finalize

Case B: Request tx_1 on receipt of fp(LP, tx_1, COMMIT), (start timer),..., RECV tx_1, fLP exists (timer stop),
Prepare->LocalPrepare->(send ourfp(LP, tx_1, COMMIT|ABORT)) -> AllPrepare ->Finalize`

Case C: Request tx_1 on receipt of LP(tx_1, COMMIT), (start timer),..., (timer expires), should the local committee even vote on anything involving tx_1 here? We don't know tx_1 or if it event exists so it likely is equivocation. Maybe Prepare(tx_1, TIMEOUT) -> LocalPrepare(tx_1, TIMEOUT) ->(send our fp(LP, tx_1, TIMEOUT))-> SomePrepare(tx_1, TIMEOUT) ->Finalize(tX_1, TIMEOUT)

Case D: We have LocalPrepare(tx_1, COMMIT), Waiting for fp(LP, tx_1, *), (start timer),..., tx_1 exists, RECV fp(LP, tx_1, COMMIT) (timer stop),
Prepare->LocalPrepare->(send ourfLP(tx_1, COMMIT|ABORT)) -> AllPrepare ->Finalize`

Case E: We have LocalPrepare(tx_1, COMMIT), Waiting for fp(LP,tx_1, *) (start timer),..., (timer expires), propose SomePrepare(tx_1, TIMEOUT) -> (send fp(SP, tx_1, TIMEOUT)) -> Finalize(tx_1, TIMEOUT)

Rather than local round that all local nodes did receive foreign data, which I think is covered by votes on AllPrepared/SomePrepared proposals, we may need to have a LocalPrepared(tx_1, TIMEOUT)' and a final foreign round sending the next LocalPrepared' to ensure that if shards didnt get the foreign data, no shard commits, I suspect this is needed anyway.


Before transactions in the `N+1`th foreign proposal for a shard, all transactions in the `N`th foreign proposal for that shard must be sequenced into the local chain as either a TIMEOUT or a LOCALPREPARE(TxId, ForeignShardId).

When a LOCALPREPARE command is found in a local proposal, there **must** be a
Prepare(tx) command for that transaction in or before the current proposal.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Prepare MUST come strictly before the LocalPrepare in a previous block. A LocalPrepare means that all nodes are aware that n-f others have prepared tx_1 . If Prepare(tx_1) is in the same block as LocalPrepare(tx_1) then we cannot be sure that we are ready to send the LocalPrepare(tx_1) to foreign shards until that block is in the commit phase.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main difference here is to make sure we start the transaction locally before committing to other shards


In the `TIMEOUT_TIME`` block (e.g. 1000 blocks, but should probably be equal to committee_size * X rounds) after the ForeignProposal command has been proposed,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add "Dummy blocks should be excluded from this count"

all transactions in the proposal must be sequenced, either as LOCALPREPAREs or TIMEOUTs. This is to cater for the case where a transaction was prepared by a foreign committee, but was never found on the network. This is unlikely to happen
in a non-malicious scenario. The more common case is that all transactions will be found and have a LOCALPREPARE, but a block at `TIMEOUT_TIME` **must** be considered invalid if there are any transactions that are not LOCALPREPARED or TIMEOUT from the foreign proposal that started the timeout.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this (invalid block) necessary? I worry about stoppages because of timer and state mismatches across local nodes if a majority are not aware of the original foreign proposal and the complexity dealing with that introduces. A non-byzantine node will include a timeout in the block eventually.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the new Command ForeignProposal (or perhaps ForeignProposalReceived is a better name), the nodes in the local committee have all agreed that they have received the foreign proposal, so if this command is in the local chain, the majority acknowledge that they have the ForeignProposal in hand


For this reason, LOCAL_PREPARES and TIMEOUTs do not count to the block size.

NOTE: ForeignProposal commands can be proposed in between a previous ForeignProposal and LocalPrepare/Timeout commands, but commands from the ForeignProposal **must** only be proposed after all transactions in the first ForeignProposal have been sequenced.
The TIMEOUT_TIME block is counted from the height where the ForeignProposal is sequenced.

ForeignProposal commands **must** appear in strict ascending order in the blockchain, but do not have to be in sequential blocks. In other words, for shard *s*, the block containing ForeignProposal(*s*, 1) must have a height lower than ForeignProposal(*s*, 2). Also, if a chain contains ForeignProposal(*s*, 1) and ForeignProposal(*s*, 3), then it **must** also contain ForeignProposal(*s*, 2).

If a node receives a foreign proposal (not the command), and it has not received
the previous foreign proposal, then it should ask the committee to provide it to them.

If the LOCAL_PREPARE command would appear in a local proposal for a transaction and is the last such LOCAL_PREPARE and all shards have voted to accept, then the LOCAL_PREPARE **must** not be present and instead an ALL_PREPARED(tx) command **must** be present in the local proposal.
Likewise, if a LOCAL_PREPARE command appears in the local proposal and is the first such to abort, then instead, a SOME_PREPARED(abort, tx) **must** be present in the local proposal.
It may happen that a LOCAL_PREPARE(tx) must be sequenced for an already aborted transaction, in which case, it should not be followed by a SOME_PREPARED(abort, tx) but instead an ALREADY_ABORTED(tx) commmand **must** be present in the local proposal.


# Change Log

| Date | Change | Author |
|:------------|:--------------|:-------|
| 17 Nov 2023 | First draft | stringhandler |

Loading