--- title: Tickets in Deku-P tags: ticket --- # Tickets in Deku-P The implementation of Deku-P is at the folder:[ deku-p/src/core](https://github.com/marigold-dev/deku/blob/main/deku-p/src), because Deku is designed to be a framework to implement parameteric chain like Deku-C or the Cookie-game. :::warning Notice that, at the moment, the implementation of Deku is very active, so the links may change theirs addresses. ::: Definition about Deku-P, Deku-C, Decookie. :::success :::spoiler - Deku-C: is a public sidechain with a WASM VM made with Deku-P - Deku-P: is an app-chain framework to build sidechain to Tezos - Decookie: is a tutorial for building an app-chain with Deku-P ![](https://hackmd.io/_uploads/B11eY1LHj.png) ::: ## Deku workflow Tezos users can transfer virtually any asset to the Deku network by first wrapping the asset as a ticket. The contract will block the funds and issue the corresponding tickets to the address in Deku. When user is ready to withdraw their assets to Layer 1, they can issue a withdraw command to one of the Deku nodes. On inclusion in a Deku block, they will receive a withdraw proof that can be submitted to Tezos to withdraw from the vault. Example of the workflow of the consensus contract [consensus.mligo](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/consensus.mligo) :::success :::spoiler - Deposit tickets via the [endpoint](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/consensus.mligo#L172) `vault_deposit` in the consensus smart contract. - Deku listens for operation on the consensus contract. When Deku sees a deposit operation, it adds the deposited ticket to its ledger. - User/Smart-contract on layer can transfer tickets to User/smart-contract (within Deku chain). - Users can withdraw tickets via the [endpoint](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/consensus.mligo#L251) `vault_withdraw` to Layer 1. :::info Examples: - [deposit entrypoint](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/consensus.mligo#L167) ``` flow: Use Tezos.read_ticket read ticket deposit Use Big_map.get_and_update to match the ticket - if there is none then return the ticket deposit - if there is some old_ticket then Tezos.join_tickets (old_ticket, ticket) and return a joined ticket. type vault_deposit = { ticket : bytes ticket; address: key_hash (* recipient: valid Deku address *) } ``` - [Withdraw entrypoint](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/consensus.mligo#L251) ``` flow: validate handle hash validate if handle.id is used validate if the caller is the owner validate if the proof match the data provided mark handle.id as used split ticket in fragment and remaining store remaining send fragment to callback type vault_withdraw = { handles_hash: blake2b; handle: vault_handle_structure; proof: vault_handle_proof; callback: vault_ticket contract; } ``` ::: The [dummy_ticket.mligo](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo) is designed as a helper. It provides functions: mint dummy tickets and deposit on Deku, burn tickets received from Deku, and execute withdraws on Deku. For example: functions [deposit_to_deku](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo#L45) and [withdraw_from_deku](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo#L57). ## Tickets There are two kinds of tickets in Deku: one is the Tezos ticket and another is the Deku ticket. For short, Deku tickets are used internally in Deku chain. Tezos ticket is the one that the user uses to deposit in and/or withdraw from Deku chain. - Deku ticket: - It is defined in the [ledger](https://github.com/marigold-dev/deku/tree/main/deku-p/src/core/ledger) folder. In short: - Deku ticket will be stored inside a `Ledger`, at a ticket table `Ticket_table`. - The ticket table is an address map `Address_map` of ticket `Tickets`. - Where address `Address` of Deku is either implicit or originated. - ticket `Tickets.t` contains the amount `Amount.t` of a ticket identity `ticket_id` map `Ticket_map`. - A ticket identity `ticket_id` of Deku contains ticketer `ticketer` and data. A ticketer of the Deku ticket can be minted by Deku contract `Contract_address` or Tezos contract `Deku_tezos.Contract_hash`. If it is a Tezos contract it means that the ticket exists on Layer 1. :::success :::spoiler A `Ledger.t` is: ![](https://hackmd.io/_uploads/HkIiVeG8i.png) A `Ticket_table.t` is: ![](https://hackmd.io/_uploads/Hyis4xz8j.png) A `Address.t` is: ![](https://hackmd.io/_uploads/r1RArxGLo.png) A `Tickets.t` is: ![](https://hackmd.io/_uploads/rJZ2ElMUo.png) A `Ticket_id.t` is: ![](https://hackmd.io/_uploads/H1l2FezLj.png) ![](https://hackmd.io/_uploads/SkH2YgfIj.png) ::: - Tezos ticket: - It is defined in the [tezos](https://github.com/marigold-dev/deku/tree/main/deku-p/src/core/tezos) folder (when use in Deku it will be renamed as `Deku_tezos`). - It is the one in the Tezos ticket, this ticket can be minted by implicit/originated Tezos addresses. Compare between Deku ticket and Tezos ticket: ![](https://hackmd.io/_uploads/S1dYQfz8o.png) ### Deposit workflow Let's have this scenario: There is a Tezos user Alex with the Tezos address `tz1...`, this user wants to deposit some tickets to Deku chain (because Deku wrapping the asset as a ticket). - Alex interacts with Tezos by calling the contract with deposit entrypoint: In this example, Alex [calls the contract](https://github.com/marigold-dev/deku/blob/main/scripts/test_e2e.sh#L131) `dummy_ticket` (this contract using Tezos to [originate](https://github.com/marigold-dev/deku/blob/main/scripts/deploy_contracts.sh#L60) and have the address `KT1xxx_dummy`) with the entrypoints [`mint_to_deku`](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo#L73). Alex has to give these information as input for `mint_to_deku`: - The address of the `consensus` contract (this is the `consensus.mligo`, this contract using Tezos to [originate](https://github.com/marigold-dev/deku/blob/main/scripts/deploy_contracts.sh#L56) and have the [address](https://github.com/marigold-dev/deku/blob/main/examples/tutorial/start.sh) `KT1LHcxdRTgyFp1TdrgodVekLFkQwzFnTJcY`), - The receiver (Deku address, for instance this [`wallet.json`](https://github.com/marigold-dev/deku/blob/main/examples/tutorial/wallet.json)), - The ticket data (in bytes), - The amount of ticket, ![](https://hackmd.io/_uploads/SyvYnkMUi.png) - Tezos contracts operation: The `dummy_ticket` contract will create a new Tezos ticket [`Tezos.create_ticket`](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo#L75) (`dummy_ticket` uses Ligo to write its contract) with the infomation that Alex provides: :::success :::spoiler ![](https://hackmd.io/_uploads/SkZ9jkzLo.png) ::: Then `dummy_ticket` will call the `consensus` contract with the entrypoint `deposit` (the function [`deposit_to_deku`](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo#L45)): :::success :::spoiler ![](https://hackmd.io/_uploads/HkEKi1M8i.png) - Deku side: This part is Deku chain consensus operates: ![](https://hackmd.io/_uploads/HkHdexf8j.png) - When Deku observes a new ticket deposit in the consensus contract, it will parse the Michelson Tezos operation to a `Tezos_operation.t` (which will have a list of Tezos ticket in the case of a deposit, the owner and the amount). - This Tezos operation is added to the mempool of Deku. - The operation will then be added in a block. - When the block is accepted, the `Tezos_operation.t` will be applied (by the function [`apply_tezos_operation`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/protocol/protocol.ml#L139) below), the Tezos ticket will be converted to a Deku ticket (at the function `ticket_id`, where it calls the function [`Ticket_id.from_tezos_ticket`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/ledger/ticket_id.ml#L77)) and added in the Deku ledger (function [`Ledger.deposit`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/ledger/ledger.ml#L116)). :::success :::spoiler ![](https://hackmd.io/_uploads/rkZ-RkMIj.png) ![](https://hackmd.io/_uploads/H1SbRkM8s.png) This Deku ticket has a form of `Ticket_id {ticketer = Tezos contract; data}`, where `contract` is the address of the `dummy_ticket` contract. (TODO: not entirely sure which contract here) The Tezos ticket has a form of `Deku_tezos.Ticket_id.{ticketer; data}` ![](https://hackmd.io/_uploads/ryExXgMIo.png) where the `Address.t` is: ![](https://hackmd.io/_uploads/rJy77xzLo.png) Note that, there is a function to convert a Tezos ticket to Deku ticket, but it is not used because at the moment the ticket is never converted to Tezos ticket, because this Tezos ticket always exists in layer 1. ### Withdraw workflow For the withdraw, Deku only allow withdraw Tezos tickets (because only those tickets exits on Layer 1). Let's have this scenario: - Alex interacts with Deku chain to have a withdraw operation hash: The Tezos user Alex wants to withdraw tickets that he deposited to Deku chain. First, Alex needs to interact with Deku chain by using the [`deku-withdraw-test`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/tests/withdraw_test.ml#L47) provided by Deku chain and create a withdraw operation, and provide the required information: - sender is the Deku address, - owner is the Tezos address (the dummy ticket address), - Deku ticket identity, - and the amount. - Deku side: This part is the Deku consensus operates: - This operation is added to the mempool. - Then the operation is added in a block. - When the block is accepted, the Deku ticket is removed from the ledger. - Alex generates withdraw proof from Deku: - After Alex receives the [withdraw operation hash](https://github.com/marigold-dev/deku/blob/main/scripts/test_e2e.sh#L155), he needs to continue to generate a [withdraw proof](https://github.com/marigold-dev/deku/blob/main/scripts/test_e2e.sh#L164). To do that, Alex uses the cli [`deku-proof-test`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/tests/proof_test.ml#L64) provides by Deku with the required input is: the withdraw operation hash. - Alex interacts with Tezos by [calling contract](https://github.com/marigold-dev/deku/blob/main/scripts/test_e2e.sh#L19) `dummy_ticket`: - Now Alex has the withdraw proof he can withdraw his tickets from Layer 1 by calling the dummy ticket contract entrypoint [`withdraw_from_deku`](https://github.com/marigold-dev/deku/blob/main/dummy_ticket.mligo#L57) with the required information: withdraw proof and the consensus contract address. - Contract operation: - The dummy ticket contract will then call the [`withdraw`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos_interop/consensus.mligo#L335) entrypoint of the consensus contract, after that the consensus contract will do the withdraw and return the funds back for the receiver address. ## Tzportal Note that Deku use Tzportal as a GUI birdge to interact with Deku. You can watch the demo at this [video tutorial](https://www.youtube.com/watch?v=qrjEaPHDlqE). ## Others functions The section below show the briefly the code of protocol (state) and the receipt. :::success :::spoiler Everything related to tickets can be found at the [deku-p/src/core/ledger ](https://github.com/marigold-dev/deku/tree/main/deku-p/src/core/ledger) folder. Everything related to Tezos can be found at [deku-p/src/core/tezos]( https://github.com/marigold-dev/deku/tree/main/deku-p/src/core/tezos). Its modules when use will be renamed as `Deku_tezos`, for example: `Deku_tezos.Address` for [`Address.ml`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/tezos/address.ml). ### Protocol and operation - [protocol.ml](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/protocol/protocol.ml): this is where function apply operations are implemented (for example: [`apply_operation`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/protocol/protocol.ml#L33), [`apply_tezos_operation`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/protocol/protocol.ml#L126)). Notice that, protocol in Deku stands for "state". - [operation.ml](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/protocol/operation.mli): in this file contains the type/shape of a ticket transfer operation. ``` type operation = | Operation_ticket_transfer of { sender : Address.t; receiver : Address.t; ticket_id : Ticket_id.t; amount : Amount.t; } | Operation_vm_transaction of { sender : Address.t; operation : string; tickets : (Ticket_id.t * N.t) list; [@opaque] } | Operation_withdraw of { sender : Address.t; owner : Deku_tezos.Address.t; ticket_id : Ticket_id.t; amount : Amount.t; } | Operation_noop of { sender : Address.t } ``` ### Receipt A [`Receipt.t`](https://github.com/marigold-dev/deku/blob/main/deku-p/src/core/protocol/receipt.ml#L3): the receipt for the ticket at the moment only inclues operation hash. ``` type receipt = | Ticket_transfer_receipt of { operation : Operation_hash.t } | Withdraw_receipt of { operation : Operation_hash.t; handle : Ledger.Withdrawal_handle.t; } | Vm_transaction_receipt of { operation : Operation_hash.t } ``` ::: ## What protocol team can do - Contribute to the design(s) of ticket in Deku: - Current design of ticket representations: - The issue is create new tickets on Deku (Deku native ticket) and withdraw them to L1. - https://github.com/marigold-dev/deku/issues/609 - Internal use as transport within Deku-chain - External use between Deku-chain to Tezos - Improve `implicit->originated` so it can pass arbitrary parameter (i.e. use `Transfer` manager operation). This will enable direct `implicit->deku` deposit. - FA2.1 compatiblility - Parametrize the ticket type and not hard-code `bytes` ## Deku team input @Pilou97: "In my opinion, we have to make sure that ticket can be deposit and withdraw with a tezos implicit address, because (maybe I am wrong) in next versions of Tezos tz1 addresses will be able to transfer/own tickets."