From c23f9854fc1fa69a36f113c4f15f48a46c49c976 Mon Sep 17 00:00:00 2001 From: Igor Sereda Date: Thu, 15 Feb 2024 05:09:34 +0300 Subject: [PATCH] L2 transactions with Tickets --- bridge_indexer/handlers/bridge_matcher.py | 4 +- .../handlers/etherlink/on_deposit.py | 22 +++++------ .../handlers/etherlink/on_withdraw.py | 14 ++++--- .../handlers/etherlink/on_xtz_deposit.py | 3 ++ .../handlers/tezos/on_rollup_call.py | 38 ++++++++----------- ...ntracked_etherlink_token-tezos_ticket.json | 2 +- .../07_untracked_l1_deposit-tezos_ticket.json | 2 +- .../14_untracked_l2_deposit-tezos_ticket.json | 20 ++++++++++ ..._untracked_l2_withdrawal-tezos_ticket.json | 20 ++++++++++ bridge_indexer/models/__init__.py | 32 ++++++++++------ .../sql/on_reindex/00_xtz_asset.sql | 10 ++--- 11 files changed, 106 insertions(+), 61 deletions(-) create mode 100644 bridge_indexer/hasura/14_untracked_l2_deposit-tezos_ticket.json create mode 100644 bridge_indexer/hasura/15_untracked_l2_withdrawal-tezos_ticket.json diff --git a/bridge_indexer/handlers/bridge_matcher.py b/bridge_indexer/handlers/bridge_matcher.py index 4d0731d..1c5027d 100644 --- a/bridge_indexer/handlers/bridge_matcher.py +++ b/bridge_indexer/handlers/bridge_matcher.py @@ -45,12 +45,12 @@ async def check_pending_etherlink_deposits(): l2_token_id='xtz', ).order_by('level', 'transaction_index') async for l2_deposit in qs: - await l2_deposit.fetch_related('l2_token', 'l2_token__tezos_ticket') + await l2_deposit.fetch_related('l2_token', 'l2_token__ticket') bridge_deposit = ( await BridgeDepositTransaction.filter( l2_transaction=None, l1_transaction__inbox_message_id__gt=0, - l1_transaction__ticket=l2_deposit.l2_token.tezos_ticket, + l1_transaction__ticket=l2_deposit.l2_token.ticket, l1_transaction__timestamp__gt=l2_deposit.timestamp - timedelta(minutes=5), l1_transaction__timestamp__lt=l2_deposit.timestamp + timedelta(minutes=5), l1_transaction__l2_account=l2_deposit.l2_account, diff --git a/bridge_indexer/handlers/etherlink/on_deposit.py b/bridge_indexer/handlers/etherlink/on_deposit.py index 9ab382a..65d25f6 100644 --- a/bridge_indexer/handlers/etherlink/on_deposit.py +++ b/bridge_indexer/handlers/etherlink/on_deposit.py @@ -14,24 +14,21 @@ from bridge_indexer.types.kernel.evm_events.deposit import Deposit -async def register_etherlink_token(token_contract: str, tezos_ticket_hash: int) -> EtherlinkToken: +async def register_etherlink_token(token_contract: str, ticket_hash: int) -> EtherlinkToken: etherlink_token = await EtherlinkToken.get_or_none(id=token_contract) - tezos_ticket = await TezosTicket.get_or_none(ticket_hash=tezos_ticket_hash) + if etherlink_token: - if etherlink_token.tezos_ticket: - pass - else: - if tezos_ticket: - etherlink_token.tezos_ticket = tezos_ticket - await etherlink_token.save() - else: + return etherlink_token + + tezos_ticket = await TezosTicket.get_or_none(pk=ticket_hash) + if tezos_ticket: etherlink_token = await EtherlinkToken.create( id=token_contract, - tezos_ticket=tezos_ticket, - tezos_ticket_hash=tezos_ticket_hash, + ticket_id=ticket_hash, ) + return etherlink_token - return etherlink_token + raise ValueError('Ticket with given hash not found', ticket_hash) async def on_deposit( @@ -56,6 +53,7 @@ async def on_deposit( transaction_index=event.data.transaction_index, l2_account=event.payload.receiver[-40:], l2_token=etherlink_token, + ticket_id=event.payload.ticket_hash, amount=event.payload.amount, inbox_message=inbox_message, ) diff --git a/bridge_indexer/handlers/etherlink/on_withdraw.py b/bridge_indexer/handlers/etherlink/on_withdraw.py index 0cf8a0b..9e95673 100644 --- a/bridge_indexer/handlers/etherlink/on_withdraw.py +++ b/bridge_indexer/handlers/etherlink/on_withdraw.py @@ -1,7 +1,3 @@ -from dipdup.context import HandlerContext -from dipdup.models import Index -from dipdup.models import IndexStatus -from dipdup.models.evm_subsquid import SubsquidEvent from tortoise.exceptions import DoesNotExist from bridge_indexer.handlers.bridge_matcher import BridgeMatcher @@ -9,6 +5,10 @@ from bridge_indexer.models import EtherlinkToken from bridge_indexer.models import EtherlinkWithdrawEvent from bridge_indexer.types.kernel.evm_events.withdrawal import Withdrawal +from dipdup.context import HandlerContext +from dipdup.models import Index +from dipdup.models import IndexStatus +from dipdup.models.evm_subsquid import SubsquidEvent async def on_withdraw( @@ -18,7 +18,10 @@ async def on_withdraw( token_contract = event.payload.ticket_owner[-40:] etherlink_token = await EtherlinkToken.get_or_none(id=token_contract) if not etherlink_token: - raise ValueError('L2 token not found!') + if event.payload.sender == event.payload.ticket_owner: + ctx.logger.info('Deposit revert found', event) + else: + raise ValueError('L2 token not found!') try: outbox_message = await OutboxMessageService.find_by_index(event.payload.outbox_level, event.payload.outbox_msg_id, ctx) @@ -40,6 +43,7 @@ async def on_withdraw( l2_account=event.payload.sender[-40:], l1_account=event.payload.receiver, l2_token=etherlink_token, + ticket_id=event.payload.ticket_hash, amount=event.payload.amount, outbox_message=outbox_message, ) diff --git a/bridge_indexer/handlers/etherlink/on_xtz_deposit.py b/bridge_indexer/handlers/etherlink/on_xtz_deposit.py index 7cb623d..c532353 100644 --- a/bridge_indexer/handlers/etherlink/on_xtz_deposit.py +++ b/bridge_indexer/handlers/etherlink/on_xtz_deposit.py @@ -1,6 +1,7 @@ from datetime import datetime from datetime import timezone +from bridge_indexer.models import TezosTicket from dipdup.context import HandlerContext from dipdup.models import Index from dipdup.models import IndexStatus @@ -28,6 +29,7 @@ async def on_xtz_deposit( return etherlink_token = await EtherlinkToken.get(id='xtz') + tezos_ticket = await TezosTicket.get(token_id='xtz') await EtherlinkDepositEvent.create( timestamp=datetime.fromtimestamp(transaction.timestamp, tz=timezone.utc), @@ -38,6 +40,7 @@ async def on_xtz_deposit( transaction_index=transaction.transaction_index, l2_account=transaction.to[-40:], l2_token=etherlink_token, + ticket=tezos_ticket, amount=transaction.value, inbox_message=None, ) diff --git a/bridge_indexer/handlers/tezos/on_rollup_call.py b/bridge_indexer/handlers/tezos/on_rollup_call.py index 632652e..315a8da 100644 --- a/bridge_indexer/handlers/tezos/on_rollup_call.py +++ b/bridge_indexer/handlers/tezos/on_rollup_call.py @@ -11,7 +11,6 @@ from bridge_indexer.handlers.bridge_matcher import BridgeMatcher from bridge_indexer.handlers.rollup_message import InboxMessageService -from bridge_indexer.models import EtherlinkToken from bridge_indexer.models import TezosDepositEvent from bridge_indexer.models import TezosTicket from bridge_indexer.models import TezosToken @@ -22,7 +21,6 @@ async def validate_ticket(parameter: LL, ctx: HandlerContext): routing_info = bytes.fromhex(parameter.bytes) - l2_receiver = routing_info[:20] l2_proxy = routing_info[20:40] or None ticket_identifier = parameter.ticket ticket_content = ticket_identifier.data @@ -58,10 +56,20 @@ async def validate_ticket(parameter: LL, ctx: HandlerContext): }, ], } - ticket_id = f'{ticket_identifier.address}_{ticket_content.nat}' - ticket = await TezosTicket.get_or_none(pk=ticket_id) + + data = Web3.solidity_keccak( + ['bytes22', 'bytes'], + [ + forge_address(ticket_identifier.address), + forge_micheline(ticket_content_micheline), + ], + ) + + ticket_hash = decode(['uint256'], data)[0] + ticket = await TezosTicket.get_or_none(pk=ticket_hash) if ticket: return ticket + token = await TezosToken.get_or_none(pk=asset_id) if not token: metadata_datasource = ctx.get_metadata_datasource('metadata') @@ -81,28 +89,13 @@ async def validate_ticket(parameter: LL, ctx: HandlerContext): type=ticket_metadata['token_type'], ) - data = Web3.solidity_keccak( - ['bytes22', 'bytes'], - [ - forge_address(ticket_identifier.address), - forge_micheline(ticket_content_micheline), - ], - ) - - ticket_hash = decode(['uint256'], data)[0] - ticket = await TezosTicket.create( - id=ticket_id, - token=token, + hash=ticket_hash, ticketer_address=ticket_identifier.address, ticket_id=ticket_content.nat, - ticket_hash=ticket_hash, + token=token, ) - async for orphan_etherlink_token in EtherlinkToken.filter(tezos_ticket_hash=ticket_hash, tezos_ticket=None): - orphan_etherlink_token.tezos_ticket = ticket - await orphan_etherlink_token.save() - return ticket @@ -111,7 +104,6 @@ async def on_rollup_call( default: TzktTransaction[DefaultParameter, RollupStorage], ) -> None: parameter = default.parameter.__root__.LL - ticket = await validate_ticket(parameter, ctx) routing_info = bytes.fromhex(parameter.bytes) l2_receiver = routing_info[:20] @@ -120,6 +112,8 @@ async def on_rollup_call( ctx.logger.warning('Invalid routing_info', parameter) return + ticket = await validate_ticket(parameter, ctx) + inbox_message = await InboxMessageService.match_transaction_with_inbox(default.data, ctx) await TezosDepositEvent.create( diff --git a/bridge_indexer/hasura/06_untracked_etherlink_token-tezos_ticket.json b/bridge_indexer/hasura/06_untracked_etherlink_token-tezos_ticket.json index 5fe7c3d..244c269 100644 --- a/bridge_indexer/hasura/06_untracked_etherlink_token-tezos_ticket.json +++ b/bridge_indexer/hasura/06_untracked_etherlink_token-tezos_ticket.json @@ -12,7 +12,7 @@ "name": "etherlink_token", "schema": "public" }, - "column": "tezos_ticket_id" + "column": "ticket_hash" } }, "source": "default" diff --git a/bridge_indexer/hasura/07_untracked_l1_deposit-tezos_ticket.json b/bridge_indexer/hasura/07_untracked_l1_deposit-tezos_ticket.json index e4d11a9..7fefa80 100644 --- a/bridge_indexer/hasura/07_untracked_l1_deposit-tezos_ticket.json +++ b/bridge_indexer/hasura/07_untracked_l1_deposit-tezos_ticket.json @@ -12,7 +12,7 @@ "name": "l1_deposit", "schema": "public" }, - "column": "ticket_id" + "column": "ticket_hash" } }, "source": "default" diff --git a/bridge_indexer/hasura/14_untracked_l2_deposit-tezos_ticket.json b/bridge_indexer/hasura/14_untracked_l2_deposit-tezos_ticket.json new file mode 100644 index 0000000..1ad42bd --- /dev/null +++ b/bridge_indexer/hasura/14_untracked_l2_deposit-tezos_ticket.json @@ -0,0 +1,20 @@ +{ + "type": "pg_create_array_relationship", + "args": { + "name": "l2_deposits", + "table": { + "name": "tezos_ticket", + "schema": "public" + }, + "using": { + "foreign_key_constraint_on": { + "table": { + "name": "l2_deposit", + "schema": "public" + }, + "column": "ticket_hash" + } + }, + "source": "default" + } +} diff --git a/bridge_indexer/hasura/15_untracked_l2_withdrawal-tezos_ticket.json b/bridge_indexer/hasura/15_untracked_l2_withdrawal-tezos_ticket.json new file mode 100644 index 0000000..ec95227 --- /dev/null +++ b/bridge_indexer/hasura/15_untracked_l2_withdrawal-tezos_ticket.json @@ -0,0 +1,20 @@ +{ + "type": "pg_create_array_relationship", + "args": { + "name": "l2_withdrawals", + "table": { + "name": "tezos_ticket", + "schema": "public" + }, + "using": { + "foreign_key_constraint_on": { + "table": { + "name": "l2_withdrawal", + "schema": "public" + }, + "column": "ticket_hash" + } + }, + "source": "default" + } +} diff --git a/bridge_indexer/models/__init__.py b/bridge_indexer/models/__init__.py index 2302dc5..f815868 100644 --- a/bridge_indexer/models/__init__.py +++ b/bridge_indexer/models/__init__.py @@ -33,15 +33,14 @@ class Meta: table = 'tezos_ticket' model = 'models.TezosTicket' - id = fields.TextField(pk=True) + hash = fields.CharField(pk=True, max_length=78) + ticketer_address = fields.CharField(max_length=36) + ticket_id = fields.TextField(default='0') token: ForeignKeyFieldInstance[TezosToken] = fields.ForeignKeyField( model_name=TezosToken.Meta.model, source_field='token_id', to_field='id', ) - ticketer_address = fields.CharField(max_length=36) - ticket_id = fields.TextField(default='0') - ticket_hash = fields.CharField(max_length=78, index=True, unique=True) class EtherlinkToken(Model): @@ -51,14 +50,12 @@ class Meta: id = fields.CharField(max_length=40, pk=True) name = fields.TextField(null=True) - tezos_ticket: ForeignKeyFieldInstance[TezosTicket] = fields.ForeignKeyField( + ticket: ForeignKeyFieldInstance[TezosTicket] = fields.ForeignKeyField( model_name=TezosTicket.Meta.model, - source_field='tezos_ticket_id', - to_field='id', + source_field='ticket_hash', + to_field='hash', unique=True, - null=True, ) - tezos_ticket_hash = fields.CharField(max_length=78, index=True) class RollupCommitment(Model): @@ -73,7 +70,7 @@ class Meta: # last_level = fields.IntField() # last_time = fields.DatetimeField() state = fields.CharField(max_length=54) - hash = fields.CharField(max_length=54) + hash = fields.CharField(max_length=54, index=True) status = fields.CharField(max_length=16) outbox_messages: fields.ReverseRelation['RollupOutboxMessage'] @@ -148,8 +145,8 @@ class Meta: l2_account = fields.CharField(max_length=40) ticket: ForeignKeyFieldInstance[TezosTicket] = fields.ForeignKeyField( model_name=TezosTicket.Meta.model, - source_field='ticket_id', - to_field='id', + source_field='ticket_hash', + to_field='hash', ) amount = fields.TextField() inbox_message: ForeignKeyFieldInstance[RollupInboxMessage] = fields.ForeignKeyField( @@ -199,6 +196,11 @@ class Meta: to_field='id', null=True, ) + ticket: ForeignKeyFieldInstance[TezosTicket] = fields.ForeignKeyField( + model_name=TezosTicket.Meta.model, + source_field='ticket_hash', + to_field='hash', + ) amount = fields.TextField() inbox_message: ForeignKeyFieldInstance[RollupInboxMessage] = fields.ForeignKeyField( model_name=RollupInboxMessage.Meta.model, @@ -222,6 +224,12 @@ class Meta: model_name=EtherlinkToken.Meta.model, source_field='token_id', to_field='id', + null=True, + ) + ticket: ForeignKeyFieldInstance[TezosTicket] = fields.ForeignKeyField( + model_name=TezosTicket.Meta.model, + source_field='ticket_hash', + to_field='hash', ) amount = fields.TextField() outbox_message: ForeignKeyFieldInstance[RollupOutboxMessage] = fields.ForeignKeyField( diff --git a/bridge_indexer/sql/on_reindex/00_xtz_asset.sql b/bridge_indexer/sql/on_reindex/00_xtz_asset.sql index 877f17c..d7110b8 100644 --- a/bridge_indexer/sql/on_reindex/00_xtz_asset.sql +++ b/bridge_indexer/sql/on_reindex/00_xtz_asset.sql @@ -1,19 +1,17 @@ insert into tezos_token (id, contract_address, token_id, name, symbol, decimals, type) values ('xtz', 'KT1000000000000000000000000000000000', '0', 'Tezos', 'XTZ', 6, 'native'); -insert into tezos_ticket (id, ticketer_address, ticket_id, ticket_hash, token_id) +insert into tezos_ticket (hash, ticketer_address, ticket_id, token_id) values ( - 'KT1Q6aNZ9aGro4DvBKwhKvVdia2UmVGsS9zE_0', + '10666650643273303508566200220257708314889526103361559239516955374962850039068', 'KT1Q6aNZ9aGro4DvBKwhKvVdia2UmVGsS9zE', '0', - '10666650643273303508566200220257708314889526103361559239516955374962850039068', 'xtz' ); -insert into etherlink_token (id, name, tezos_ticket_hash, tezos_ticket_id) +insert into etherlink_token (id, name, ticket_hash) values ( 'xtz', 'ethXTZ', - '10666650643273303508566200220257708314889526103361559239516955374962850039068', - 'KT1Q6aNZ9aGro4DvBKwhKvVdia2UmVGsS9zE_0' + '10666650643273303508566200220257708314889526103361559239516955374962850039068' );