From cc4ab170185e3d0955b680430e0e225ed46da5ff Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 30 Jan 2024 16:36:00 -0500 Subject: [PATCH] docs: Update ADR-070 (#19296) --- ...t.md => adr-070-unordered-transactions.md} | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) rename docs/architecture/{adr-070-unordered-account.md => adr-070-unordered-transactions.md} (90%) diff --git a/docs/architecture/adr-070-unordered-account.md b/docs/architecture/adr-070-unordered-transactions.md similarity index 90% rename from docs/architecture/adr-070-unordered-account.md rename to docs/architecture/adr-070-unordered-transactions.md index c2d6e382f13b..7d29f0fbc65d 100644 --- a/docs/architecture/adr-070-unordered-account.md +++ b/docs/architecture/adr-070-unordered-transactions.md @@ -1,8 +1,9 @@ -# ADR 070: Un-Ordered Transaction Inclusion +# ADR 070: Unordered Transactions ## Changelog * Dec 4, 2023: Initial Draft (@yihuang, @tac0turtle, @alexanderbez) +* Jan 30, 2024: Include section on deterministic transaction encoding ## Status @@ -49,7 +50,7 @@ and limit the size of the dictionary. message TxBody { ... - bool unordered = 4; + bool unordered = 4; } ``` @@ -57,7 +58,7 @@ message TxBody { In order to provide replay protection, a user should ensure that the transaction's TTL value is relatively short-lived but long enough to provide enough time to be -included in a block, e.g. ~H+50. +included in a block, e.g. ~H+50. We facilitate this by storing the transaction's hash in a durable map, `UnorderedTxManager`, to prevent duplicates, i.e. replay attacks. Upon transaction ingress during `CheckTx`, @@ -107,7 +108,7 @@ func NewUnorderedTxManager() *UnorderedTxManager { blockCh: make(chan uint64, 16), txHashes: make(map[TxHash]uint64), } - + return m } @@ -182,13 +183,13 @@ func (m *UnorderedTxManager) purgeLoop() error { // channel closed break } - + latest := *blocks[len(blocks)-1] hashes := m.expired(latest) if len(hashes) > 0 { m.purge(hashes) } - + // avoid burning cpu in catching up phase time.Sleep(PurgeLoopSleepMS * time.Millisecond) } @@ -274,9 +275,17 @@ func (d *DedupTxDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, } ``` -### `OnNewBlock` +### Transaction Hashes + +It is absolutely vital that transaction hashes are deterministic, i.e. transaction +encoding is not malleable. If a given transaction, which is otherwise valid, can +be encoded to produce different hashes, which reflect the same valid transaction, +then a duplicate unordered transaction can be submitted and included in a block. -Wire the `OnNewBlock` method of `UnorderedTxManager` into the BaseApp's ABCI `Commit` event. +In order to prevent this, transactions should be encoded in a deterministic manner. +[ADR-027](./adr-027-deterministic-protobuf-serialization.md) provides such a mechanism. +However, it is important to note that the way a transaction is signed should ensure +ADR-027 is followed. E.g. we want to avoid Amino signing. ### State Management @@ -303,7 +312,8 @@ Alternatively, we can write all the transactions to consensus state. ### Negative -* Start up overhead to scan historical blocks. +* Requires additional storage overhead and management of processed unordered + transactions that exist outside of consensus state. ## References