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: appeals undetermined transactions #657

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
021f10e
feat: add rollup transaction db table
kstroobants Oct 22, 2024
eca17e5
fix: drop audit table, change id and nonce of rollup, only make one f…
kstroobants Oct 23, 2024
9184749
create rollup transaction for every validator
kstroobants Nov 6, 2024
6daee80
add function to mock in consensus test
kstroobants Nov 6, 2024
90ea2c1
feat: add appeal window, accepted queue, basic test
kstroobants Nov 7, 2024
bb30590
fix: old tests were stuck on accepted state, add usage of thread
kstroobants Nov 7, 2024
1e1958c
refactor consensus into states
kstroobants Nov 11, 2024
2708f13
feat: added appeal flow when transaction is accepted including the lo…
kstroobants Nov 13, 2024
e3fffde
fix: adding tests for appeals and fixing minor bugs
kstroobants Nov 15, 2024
3d00e34
refactor: merge main and PR #573 into this branch
kstroobants Nov 18, 2024
f5c3af1
feat: add appeal_failed in db, select new validators when appealed ba…
kstroobants Nov 24, 2024
27624bb
docs: cleanup consensus mechanism base file
kstroobants Nov 24, 2024
d315fd1
test: checking the number of validators for different appeals
kstroobants Nov 25, 2024
76b0f6d
feat: adding appeal window to undetermined state
kstroobants Nov 25, 2024
00e90e1
feat: change timestamp_accepted and add appeal_undetermined in database
kstroobants Nov 25, 2024
4dfe115
feat: undetermined to pending, activate frontend button in undetermin…
kstroobants Nov 26, 2024
9cc27f1
feat: leader only has no appeal button and no appeal window
kstroobants Nov 26, 2024
33a7f33
feat: implement the state transitions to process the appeal
kstroobants Nov 27, 2024
f2c626e
test: add test for leader appeals
kstroobants Nov 28, 2024
b843377
refactor: merge 593-appeals-add-validators-when-appealed into 604-app…
kstroobants Dec 2, 2024
b7daed7
refactor: merge 604-appeals-implement-sequential-appeals-fail into 63…
kstroobants Dec 2, 2024
be2be7d
refactor: merge main into 604-appeals-implement-sequential-appeals-fail
kstroobants Dec 12, 2024
afb13f6
refactor: merging changed file permissions
kstroobants Dec 12, 2024
1311304
Merge branch 'main' into 604-appeals-implement-sequential-appeals-fail
kstroobants Dec 12, 2024
a14ef91
fix: appealing a write method gave a KeyError because of wrong conver…
kstroobants Dec 12, 2024
70a85cf
docs: update transaction_processor argument description
kstroobants Dec 12, 2024
f34870e
fix: all appeals disagreed because of pending_transactions type
kstroobants Dec 12, 2024
089d7af
merge 604-appeals-implement-sequential-appeals-fail into 638-appeals-…
kstroobants Dec 13, 2024
722501f
refactor: undo change because of merge
kstroobants Dec 13, 2024
e2c9d4a
fix: do not reset finality window when leader appeal failed, leader_o…
kstroobants Dec 13, 2024
498e8f8
fix: set value in database migration file
kstroobants Dec 13, 2024
b529c8f
fix: add leader_only check for modal appeal button, comment out modal…
kstroobants Dec 13, 2024
698c74e
fix: do not show appeal button when finality window is finished, chec…
kstroobants Dec 13, 2024
8d26d8b
fix: we do not emit messages when the transaction goes from undetermi…
kstroobants Dec 19, 2024
a5b15db
refactor: merge main into 638-appeals-undetermined-transactions
kstroobants Dec 19, 2024
6024107
fix: complete merge
kstroobants Dec 19, 2024
60d280a
fix: redirect leader appeal is processed by appeal queue, not pending…
kstroobants Dec 20, 2024
8357219
fix: test increase wait time to get to finalized
kstroobants Dec 20, 2024
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
376 changes: 249 additions & 127 deletions backend/consensus/base.py

Large diffs are not rendered by default.

20 changes: 13 additions & 7 deletions backend/database_handler/chain_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ def __init__(self, session: Session):
self.all_validators = self.validators_registry.get_all_validators()
self.pending_transactions = self._load_pending_transactions()
self.num_validators = len(self.all_validators)
self.accepted_transactions = self._load_accepted_transactions()
self.accepted_undetermined_transactions = (
self._load_accepted_undetermined_transactions()
)

def _load_pending_transactions(self) -> List[dict]:
"""Load and return the list of pending transactions from the database."""
Expand All @@ -41,19 +43,23 @@ def get_all_validators(self):
"""Return the list of all validators."""
return self.all_validators

def _load_accepted_transactions(self) -> List[dict]:
"""Load and return the list of accepted transactions from the database."""
def _load_accepted_undetermined_transactions(self) -> List[dict]:
"""Load and return the list of accepted and undetermined transactions from the database."""

accepted_transactions = (
self.session.query(Transactions)
.filter(Transactions.status == TransactionStatus.ACCEPTED)
.filter(
(Transactions.status == TransactionStatus.ACCEPTED)
| (Transactions.status == TransactionStatus.UNDETERMINED)
)
.order_by(Transactions.timestamp_awaiting_finalization)
.all()
)
return [
TransactionsProcessor._parse_transaction_data(transaction)
for transaction in accepted_transactions
]

def get_accepted_transactions(self):
"""Return the list of accepted transactions."""
return self.accepted_transactions
def get_accepted_undetermined_transactions(self):
"""Return the list of accepted and undetermined transactions."""
return self.accepted_undetermined_transactions
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""appeal_undetermined

Revision ID: a4a32d27dde2
Revises: 2a4ac5eb9455
Create Date: 2024-11-25 14:49:46.916279

"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "a4a32d27dde2"
down_revision: Union[str, None] = "2a4ac5eb9455"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"transactions", sa.Column("appeal_undetermined", sa.Boolean(), nullable=True)
)
op.execute(
"UPDATE transactions SET appeal_undetermined = FALSE WHERE appeal_undetermined IS NULL"
)
op.alter_column("transactions", "appeal_undetermined", nullable=False)
op.add_column(
"transactions",
sa.Column("timestamp_awaiting_finalization", sa.BigInteger(), nullable=True),
)
op.execute(
"UPDATE transactions SET timestamp_awaiting_finalization = 0 WHERE timestamp_awaiting_finalization IS NULL"
)
op.drop_column("transactions", "timestamp_accepted")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"transactions",
sa.Column(
"timestamp_accepted", sa.BIGINT(), autoincrement=False, nullable=True
),
)
op.execute(
"UPDATE transactions SET timestamp_accepted = 0 WHERE timestamp_accepted IS NULL"
)
op.drop_column("transactions", "timestamp_awaiting_finalization")
op.drop_column("transactions", "appeal_undetermined")
# ### end Alembic commands ###
5 changes: 4 additions & 1 deletion backend/database_handler/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ class Transactions(Base):
init=False,
)
appealed: Mapped[bool] = mapped_column(Boolean, default=False)
timestamp_accepted: Mapped[Optional[int]] = mapped_column(BigInteger, default=None)
appeal_undetermined: Mapped[bool] = mapped_column(Boolean, default=False)
timestamp_awaiting_finalization: Mapped[Optional[int]] = mapped_column(
BigInteger, default=None
)


class Validators(Base):
Expand Down
26 changes: 19 additions & 7 deletions backend/database_handler/transactions_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ def _parse_transaction_data(transaction_data: Transactions) -> dict:
],
"ghost_contract_address": transaction_data.ghost_contract_address,
"appealed": transaction_data.appealed,
"timestamp_accepted": transaction_data.timestamp_accepted,
"timestamp_awaiting_finalization": transaction_data.timestamp_awaiting_finalization,
"appeal_failed": transaction_data.appeal_failed,
"appeal_undetermined": transaction_data.appeal_undetermined,
}

@staticmethod
Expand Down Expand Up @@ -225,8 +226,9 @@ def insert_transaction(
),
ghost_contract_address=ghost_contract_address,
appealed=False,
timestamp_accepted=None,
timestamp_awaiting_finalization=None,
appeal_failed=0,
appeal_undetermined=False,
)

self.session.add(new_transaction)
Expand Down Expand Up @@ -348,16 +350,18 @@ def set_transaction_appeal(self, transaction_hash: str, appeal: bool):
)
transaction.appealed = appeal

def set_transaction_timestamp_accepted(
self, transaction_hash: str, timestamp_accepted: int = None
def set_transaction_timestamp_awaiting_finalization(
self, transaction_hash: str, timestamp_awaiting_finalization: int = None
):
transaction = (
self.session.query(Transactions).filter_by(hash=transaction_hash).one()
)
if timestamp_accepted:
transaction.timestamp_accepted = timestamp_accepted
if timestamp_awaiting_finalization:
transaction.timestamp_awaiting_finalization = (
timestamp_awaiting_finalization
)
else:
transaction.timestamp_accepted = int(time.time())
transaction.timestamp_awaiting_finalization = int(time.time())

def set_transaction_appeal_failed(self, transaction_hash: str, appeal_failed: int):
if appeal_failed < 0:
Expand All @@ -366,3 +370,11 @@ def set_transaction_appeal_failed(self, transaction_hash: str, appeal_failed: in
self.session.query(Transactions).filter_by(hash=transaction_hash).one()
)
transaction.appeal_failed = appeal_failed

def set_transaction_appeal_undetermined(
self, transaction_hash: str, appeal_undetermined: bool
):
transaction = (
self.session.query(Transactions).filter_by(hash=transaction_hash).one()
)
transaction.appeal_undetermined = appeal_undetermined
11 changes: 8 additions & 3 deletions backend/domain/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ class Transaction:
created_at: str | None = None
ghost_contract_address: str | None = None
appealed: bool = False
timestamp_accepted: int | None = None
timestamp_awaiting_finalization: int | None = None
appeal_failed: int = 0
appeal_undetermined: bool = False

def to_dict(self):
return {
Expand All @@ -106,8 +107,9 @@ def to_dict(self):
"created_at": self.created_at,
"ghost_contract_address": self.ghost_contract_address,
"appealed": self.appealed,
"timestamp_accepted": self.timestamp_accepted,
"timestamp_awaiting_finalization": self.timestamp_awaiting_finalization,
"appeal_failed": self.appeal_failed,
"appeal_undetermined": self.appeal_undetermined,
}

@classmethod
Expand All @@ -131,6 +133,9 @@ def from_dict(cls, input: dict) -> "Transaction":
created_at=input.get("created_at"),
ghost_contract_address=input.get("ghost_contract_address"),
appealed=input.get("appealed"),
timestamp_accepted=input.get("timestamp_accepted"),
timestamp_awaiting_finalization=input.get(
"timestamp_awaiting_finalization"
),
appeal_failed=input.get("appeal_failed", 0),
appeal_undetermined=input.get("appeal_undetermined", False),
)
25 changes: 23 additions & 2 deletions frontend/src/components/Simulator/TransactionItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const transactionsStore = useTransactionsStore();

const props = defineProps<{
transaction: TransactionItem;
finalityWindow: number;
}>();

const isDetailsModalOpen = ref(false);
Expand Down Expand Up @@ -55,7 +56,7 @@ const handleSetTransactionAppeal = () => {
watch(
() => props.transaction.status,
(newStatus) => {
if (newStatus !== 'ACCEPTED') {
if (newStatus !== 'ACCEPTED' && newStatus !== 'UNDETERMINED') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

@kstroobants what's the reason of this check? can't we rely in the appeal property of the transaction?

isAppealed.value = false;
}
},
Expand Down Expand Up @@ -156,7 +157,11 @@ function prettifyTxData(x: any): any {
as="button"
@click.stop="handleSetTransactionAppeal"
:class="{ '!bg-green-500': isAppealed }"
v-if="transaction.status == 'ACCEPTED'"
v-if="
(transaction.data.leader_only == false) &&
(transaction.status == 'ACCEPTED' || transaction.status == 'UNDETERMINED') &&
((Date.now() / 1000) - transaction.data.timestamp_awaiting_finalization <= finalityWindow)
"
v-tooltip="'Appeal transaction'"
>
<div class="flex items-center gap-1">
Expand Down Expand Up @@ -226,6 +231,22 @@ function prettifyTxData(x: any): any {
>
{{ transaction.status }}
</TransactionStatusBadge>
<!-- <TransactionStatusBadge
as="button"
@click.stop="handleSetTransactionAppeal"
:class="{ '!bg-green-500': isAppealed }"
v-if="
(transaction.data.leader_only == false) &&
(transaction.status == 'ACCEPTED' || transaction.status == 'UNDETERMINED') &&
((Date.now() / 1000) - transaction.data.timestamp_awaiting_finalization <= finalityWindow)
"
v-tooltip="'Appeal transaction'"
>
<div class="flex items-center gap-1">
APPEAL
<GavelIcon class="h-3 w-3" />
</div>
</TransactionStatusBadge> -->
</p>
</div>

Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/Simulator/TransactionsList.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed } from 'vue';
import { ref, computed, defineProps } from 'vue';
import { useContractsStore, useTransactionsStore } from '@/stores';
import { TrashIcon } from '@heroicons/vue/24/solid';
import TransactionItem from './TransactionItem.vue';
Expand All @@ -9,6 +9,10 @@ import EmptyListPlaceholder from '@/components/Simulator/EmptyListPlaceholder.vu
const contractsStore = useContractsStore();
const transactionsStore = useTransactionsStore();

const props = defineProps({
finalityWindow: Number,
});

const transactions = computed(() => {
const contractTransactions = transactionsStore.transactions.filter(
(t) => t.localContractId === contractsStore.currentContractId,
Expand Down Expand Up @@ -54,6 +58,7 @@ const handleClearTransactions = () => {
v-for="transaction in transactions"
:key="transaction.hash"
:transaction="transaction"
:finalityWindow="props.finalityWindow ?? 0"
/>
</div>

Expand Down
1 change: 0 additions & 1 deletion frontend/src/services/JsonRpcService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ export class JsonRpcService implements IJsonRpcService {
}

async setFinalityWindowTime(time: number): Promise<any> {
console.log('Setting finality window time:', time, 'Type:', typeof time);
return this.callRpcMethod<any>(
'sim_setFinalityWindowTime',
[time],
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/views/Simulator/RunDebugView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ const isFinalityWindowValid = computed(() => {
id="tutorial-write-methods"
:leaderOnly="leaderOnly"
/>
<TransactionsList id="tutorial-tx-response" />
<TransactionsList
id="tutorial-tx-response"
:finalityWindow="finalityWindow"
/>
</template>
</template>

Expand Down
Loading
Loading