Просмотр исходного кода

doc/spec/contract/vesting: formal definitions added

skoupidi 5 месяцев назад
Родитель
Сommit
eb0a98572b

+ 3 - 0
doc/src/SUMMARY.md

@@ -102,6 +102,9 @@
     - [Concepts](spec/contract/deploy/concepts.md)
     - [Scheme](spec/contract/deploy/scheme.md)
   - [Vesting](spec/contract/vesting/vesting.md)
+    - [Concepts](spec/contract/vesting/concepts.md)
+    - [Model](spec/contract/vesting/model.md)
+    - [Scheme](spec/contract/vesting/scheme.md)
 
 # P2P API Tutorial
 

+ 60 - 0
doc/src/spec/contract/vesting/concepts.md

@@ -0,0 +1,60 @@
+# Concepts
+
+The vesting process is divided in a few steps that are outlined below:
+
+* **Vest:** a vesting configuration is submitted to the blockchain.
+* **Withdraw:** vestee can withdraw some amount of their vested coin.
+* **Forfeit:** vesting authority forfeits a specific vesting.
+* **Exec:** overlay function over `Withdraw` and `Forfeit`, used as the
+  spend hook binding the coins to these contract calls.
+
+## Vest
+
+Vesting authority submits a vesting configuration on-chain, along with
+a chained transfer call burning the to-be-vested input coins, which
+must be for the same token, and minting a new coin with their total
+amount for a shared secret address, using the contracts' `Exec` call
+spend-hook, effectivelly becoming usable only withing the vesting
+contract context.
+
+> Note: There is a limitation though; the vested coin can only be
+> controlled by a single address. To overcome this, when the vesting
+> authority creates the vested coin, instead of using the recipients
+> actual address, it generates a new random one, which is shared with
+> the vestee(in a safe off-chain manner), so the coin can be controlled
+> by both parties.
+
+> Note: Since vesting requires a 1-1 vested coin to config matching, it
+> means that those coins can be tracked by the vesting configuration
+> bulla. It doesn't affect rest anonimity, since it's specific to the
+> vesting contract flow and no other information can be derived by it.
+
+## Withdraw
+
+After some time has passed, the vestee can withdraw some amount from
+their vested coin, which is done by a chained transfer call burning the
+existing vested coin and creating two output coins; one which will be a
+normal coin for a withdrawal address, and a second one representing the
+remaining balance using the spend hook of the vesting contract. This
+call is responsible to define the available-to-withdraw amount, along
+with ensuring the chained transfer call second output correctly
+represents the remaining balance vested coin. We don't care if that
+becomes a zero value coin, since it won't be usable anymore, and we
+want all our outputs to look the same, so the final withdrawl cannot be
+tracked.
+
+> Note: A medatada leak exists though; the final withdrawl cannot be
+> conventionally tracked, since nobody but the parties knows when the
+> remaining balance coin becomes a zero value one, but someone tracking
+> all the withdrawls calls for a specific vesting configuration can
+> assume that the vesting has ended, if no other withdrawl is observed
+> after some time period. Still, they can't prove that the vesting has
+> concluded without access to the vesting information and/or the shared
+> secret address.
+
+## Forfeit
+
+With this call, a vesting authority is able to forfeit a specific
+vesting, by removing the vesting configuration, burning the remaining
+balance vested coin and mint a new one to a recipient address, using a
+chained transfer call.

+ 82 - 0
doc/src/spec/contract/vesting/model.md

@@ -0,0 +1,82 @@
+# Model
+
+Let $\t{Bulla}$ be defined as in the section [Bulla Commitments][1].
+
+Let $ℙₚ, 𝔽ₚ, \mathcal{X}, \mathcal{Y}, \t{𝔹⁶⁴2𝔽ₚ}$ be defined as in the
+section [Pallas and Vesta][2].
+
+Let $\t{Coin}$ be defined as in the section [Coin][3].
+
+## Vesting Configuration
+
+The vesting configuration contains the main parameters that define the
+vesting operation:
+
+* The vesting authority public key $VAPK$ controls the vesting
+  configuration.
+* The vestee public key $VPK$ for withdrawls.
+* The shared secret public key $SPK$ controls who can use the vested
+  coin.
+* Token $t$ is the token type of the to-be-vested input coins.
+* Total $T$ is the total amount of the to-be-vested input coins.
+* Cliff $C$ is the amount unlocked at the start blockwindow $S$.
+* Start $S$ and end $E$ are the blockwindows defining when vesting
+  starts and ends.
+* Blockwindow value $V$ is the amount unlocked on each blockwindow.
+
+Define the vesting configuration $VC$ params:
+$$ \begin{aligned}
+  \t{Params}_\t{VC}.\t{VAPK} &∈ ℙₚ \\
+  \t{Params}_\t{VC}.\t{VPK} &∈ ℙₚ \\
+  \t{Params}_\t{VC}.\t{SPK} &∈ ℙₚ \\
+  \t{Params}_\t{VC}.τ &∈ 𝔽ₚ \\
+  \t{Params}_\t{VC}.T &∈ ℕ₆₄ \\
+  \t{Params}_\t{VC}.C &∈ ℕ₆₄ \\
+  \t{Params}_\t{VC}.S &∈ ℕ₆₄ \\
+  \t{Params}_\t{VC}.E &∈ ℕ₆₄ \\
+  \t{Params}_\t{VC}.V &∈ ℕ₆₄
+\end{aligned} $$
+
+```rust
+TODO: add model definition path
+```
+
+$$ \t{Bulla}_\t{VC} : \t{Params}_\t{VC} × 𝔽ₚ → 𝔽ₚ $$
+$$ \begin{aligned}
+\t{Bulla}_\t{VC}(p, b_\t{VC}) = \t{Bulla}( \\
+\mathcal{X}(p.\t{VAPK}), \mathcal{Y}(p.\t{VAPK}), \\
+\mathcal{X}(p.\t{VPK}), \mathcal{Y}(p.\t{VPK}), \\
+\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}), \\
+p.τ, \\
+ℕ₆₄2𝔽ₚ(p.T), \\
+ℕ₆₄2𝔽ₚ(p.C), \\
+ℕ₆₄2𝔽ₚ(p.S), \\
+ℕ₆₄2𝔽ₚ(p.E), \\
+ℕ₆₄2𝔽ₚ(p.V), \\
+b_\t{VC} \\
+)
+\end{aligned} $$
+
+> Note: Since a vesting configuration bulla is derived using a random
+> blinding factor, it's safe to use the same parameters to generate
+> different vesting configurations.
+
+## Blockwindow
+
+Time limits on vesting configurations are expressed in 1 day windows.
+Since proofs cannot guarantee which block they get into, we therefore
+must modulo the block height a certain number which we use in the
+proofs.
+
+```rust
+TODO: add definition path
+```
+
+which can be used like this:
+```rust
+TODO: add usage example path
+```
+
+[1]: ../../crypto-schemes.md#bulla-commitments
+[2]: ../../crypto-schemes.md#pallas-and-vesta
+[3]: ../money/model.md#coin

+ 305 - 0
doc/src/spec/contract/vesting/scheme.md

@@ -0,0 +1,305 @@
+# Scheme
+
+<!-- toc -->
+
+Let $\t{Params}_\t{VC}, \t{Bulla}_\t{VC}$ be defined as in
+[Vesting Configuration Model](model.md).
+
+Let $\t{Coin}$ be defined as in the section [Coin][1].
+
+Let $ℙₚ, 𝔽ₚ, \mathcal{X}, \mathcal{Y}, \t{𝔹⁶⁴2𝔽ₚ}$ be defined as in the
+section [Pallas and Vesta][2].
+
+Let $t₀ = \t{BlockWindow} ∈ 𝔽ₚ$ be the current blockwindow as defined
+in [Blockwindow](model.md#blockwindow).
+
+Let $\t{PoseidonHash}$ be defined as in the section
+[PoseidonHash Function](../../crypto-schemes.md#poseidonhash-function).
+
+Let $\t{ElGamal.Encrypt}, \t{ElGamalEncNote}ₖ$ be defined as in the
+section [Verifiable In-Band Secret Distribution][3].
+
+Denote the Vesting contract ID by $\t{CID}_\t{V} ∈ 𝔽ₚ$ and its `Exec`
+function spend hook by $\t{SH}_\t{V} ∈ 𝔽ₚ$.
+
+## Vest
+
+This function creates a vesting configuration bulla $ℬ_\t{VC}$. We
+commit to the vesting configuration params and then add the bulla to
+the set, along with the vested coin $\t{Coin}$ minted by the child
+`Money::transfer()` call. Each vesting configuration keeps track of its
+minted coins, to ensure that only those can be burned in next actions,
+creating a sequence of coins, enabling the contract to keep track of
+remaining balances anonymously. Additionally, we verify the minted
+vesting coin is encrypted for the configuration shared secret key,
+ensuring both parties have access to it.
+
+* Wallet builder: `TODO: add client path`
+* WASM VM code: `TODO: add entrypoint path`
+* ZK proof: `TODO: add proof path`
+
+### Function Params
+
+Define the vest function params
+$$ \begin{aligned}
+  ℬ_\t{VC} &∈ \t{im}(\t{Bulla}_\t{VC}) \\
+  \t{SPK} &∈ ℙₚ
+\end{aligned} $$
+
+```rust
+TODO: Add call params path
+```
+
+### Contract Statement
+
+**Vesting configuration bulla uniqueness** &emsp; whether $ℬ_\t{VC}$
+already exists. If yes then fail.
+
+Let there be a prover auxiliary witness inputs:
+$$ \begin{aligned}
+  VAx &∈ 𝔽ₚ \\
+  VPK &∈ 𝔽ₚ \\
+  Sx &∈ 𝔽ₚ \\
+  τ &∈ 𝔽ₚ \\
+  T &∈ ℕ₆₄ \\
+  C &∈ ℕ₆₄ \\
+  S &∈ ℕ₆₄ \\
+  E &∈ ℕ₆₄ \\
+  V &∈ ℕ₆₄ \\
+  b_\t{VC} &∈ 𝔽ₚ \\
+  b_\t{Coin} &∈ 𝔽ₚ
+\end{aligned} $$
+
+Attach a proof $π$ such that the following relations hold:
+
+**Proof that start blockwindow is greater than current blockwindow**
+&emsp; $S > t₀$.
+
+**Proof that end blockwindow is greater than start blockwindow** &emsp;
+$E > S$.
+
+**Proof that total is greater than cliff** &emsp; $T >= C$.
+
+**Proof that blockwindow value is valid** &emsp; $T == (E - S) * V +
+C$.
+
+**Proof of vesting authority public key ownership** &emsp; $\t{VAPK} =
+\t{DerivePubKey}(VAx)$.
+
+**Proof of shared secret public key ownership** &emsp; $\t{SPK} =
+\t{DerivePubKey}(Sx)$.
+
+**Vesting configuration bulla integrity** &emsp; $ℬ =
+\t{Bulla}_\t{VC}(\mathcal{X}(p.\t{VAPK}), \mathcal{Y}(p.\t{VAPK}),
+\mathcal{X}(p.\t{VPK}), \mathcal{Y}(p.\t{VPK}),
+\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}), t, T, C, S, E, V,
+b_\t{VC})$
+
+**Minted vested coin integrity** &emsp; $Coin =
+\t{PoseidonHash}(\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}), T, t,
+\t{CID}_\t{V}, \t{SH}_\t{V}, ℬ, b_\t{Coin})$
+
+**Verifiable vested coin note encryption** &emsp;
+let $𝐧 = (c.v, c.τ, c.\t{SH}, c.\t{UD}, c.n)$, and verify
+$a = \t{ElGamal}.\t{Encrypt}(𝐧, \t{esk}, d.\t{SPK})$.
+
+### Signatures
+
+There should be a single signature attached, which uses
+$\t{SPK}$ as the signature public key.
+
+## Withdraw
+
+This function enables the vestee to withdraw the corresponding unlocked
+value up to that blockwindow. The child `Money::transfer()` call must
+contain a single input, the vested coin we burn, and two outputs. The
+first one being the withdrawed one while the second one is the
+remaining vested balance coin. Both coins values are verified by the
+vesting configuration rules, and we store the second one as the current
+vested coin, to burn in next actions. Additionally, we verify the
+second/vested coin is encrypted for the configuration shared secret
+key, ensuring both parties have access to it.
+
+* Wallet builder: `TODO: add client path`
+* WASM VM code: `TODO: add entrypoint path`
+* ZK proof: `TODO: add proof path`
+
+### Function Params
+
+Define the withdraw function params
+$$ \begin{aligned}
+  ℬ_\t{VC} &∈ \t{im}(\t{Bulla}_\t{VC}) \\
+  \t{SPK} &∈ ℙₚ
+\end{aligned} $$
+
+```rust
+TODO: Add call params path
+```
+
+### Contract Statement
+
+**Vesting configuration bulla existance** &emsp; whether $ℬ_\t{VC}$
+exists. If no then fail.
+
+**Burned vested coin existance** &emsp; whether the burned coin
+$\t{BCoin}$ matches the vesting configuration record one. If no then
+fail.
+
+Let there be a prover auxiliary witness inputs:
+$$ \begin{aligned}
+  VAPK &∈ 𝔽ₚ \\
+  Vx &∈ 𝔽ₚ \\
+  Sx &∈ 𝔽ₚ \\
+  τ &∈ 𝔽ₚ \\
+  T &∈ ℕ₆₄ \\
+  C &∈ ℕ₆₄ \\
+  S &∈ ℕ₆₄ \\
+  E &∈ ℕ₆₄ \\
+  V &∈ ℕ₆₄ \\
+  b_\t{VC} &∈ 𝔽ₚ \\
+  Bv &∈ ℕ₆₄ \\
+  b_\t{BCoin} &∈ 𝔽ₚ \\
+  x_c &∈ 𝔽ₚ \\
+  Cv &∈ ℕ₆₄ \\
+  b_\t{Coin} &∈ 𝔽ₚ
+\end{aligned} $$
+
+Attach a proof $π$ such that the following relations hold:
+
+**Proof of vestee public key ownership** &emsp; $\t{VPK} =
+\t{DerivePubKey}(Vx)$.
+
+**Proof of shared secret public key ownership** &emsp; $\t{SPK} =
+\t{DerivePubKey}(Sx)$.
+
+**Vesting configuration bulla integrity** &emsp; $ℬ =
+\t{Bulla}_\t{VC}(\mathcal{X}(p.\t{VAPK}), \mathcal{Y}(p.\t{VAPK}),
+\mathcal{X}(p.\t{VPK}), \mathcal{Y}(p.\t{VPK}),
+\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}), t, T, C, Cb, S, E, V,
+b_\t{VC})$
+
+**Proof that current blockwindow is greater than start blockwindow**
+&emsp; $t₀ >= S$.
+
+TODO: cond_select statement to pick current or end blockwindow
+
+**Proof of withdraw amount correctness** &emsp;
+$$ \begin{aligned}
+CurrentBlockwindow = CondSelect(BlockwindowCond, t₀, E); \\
+BlockwindowsPassed = CurrentBlockwindow - S; \\
+Available = (BlockwindowsPassed * V) + C; \\
+Withdrawn = T - Bv; \\
+WithdrawlCoinValue = Available - Withdrawn; \\
+VestingChangeValue = T - (Withdrawn + WithdrawlCoinValue);
+\end{aligned} $$
+
+Verify the child `Money::transfer()` call correctnes:
+
+**Burned vested coin integrity** &emsp; $BCoin =
+\t{PoseidonHash}(\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}),
+Bv, t, \t{CID}_\t{V}, \t{SH}_\t{V}, ℬ, b_\t{Coin})$
+
+**Burned vested coin nullifier integrity** &emsp; $\cN =
+\t{PoseidonHash}(x_c, BCoin)$
+
+**Minted vested coin integrity** &emsp; $Coin =
+\t{PoseidonHash}(\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}),
+VestingChangeValue, t, \t{CID}_\t{V}, \t{SH}_\t{V}, ℬ, b_\t{Coin})$
+
+**Verifiable vested coin note encryption** &emsp;
+let $𝐧 = (c.v, c.τ, c.\t{SH}, c.\t{UD}, c.n)$, and verify
+$a = \t{ElGamal}.\t{Encrypt}(𝐧, \t{esk}, d.\t{SPK})$.
+
+### Signatures
+
+There should be a single signature attached, which uses
+$\t{SPK}$ as the signature public key.
+
+## Forfeit
+
+This function enables the vesting authority to forfeit a vesting
+configuration, withdrawing the rest of vested value. The child
+`Money::transfer()` call must containg a single input, the vested coin
+we burn, and a single output, the newlly minted coin. Both coins values
+are verified by the vesting configuration rules, and we remove the
+vesting configuration bulla $ℬ_\t{VC}$ entry from the set.
+
+* Wallet builder: `TODO: add client path`
+* WASM VM code: `TODO: add entrypoint path`
+* ZK proof: `TODO: add proof path`
+
+### Function Params
+
+Define the vest function params
+$$ \begin{aligned}
+  ℬ_\t{VC} &∈ \t{im}(\t{Bulla}_\t{VC}) \\
+  \t{SPK} &∈ ℙₚ
+\end{aligned} $$
+
+```rust
+TODO: Add call params path
+```
+
+### Contract Statement
+
+**Vesting configuration bulla existance** &emsp; whether $ℬ_\t{VC}$
+exists. If no then fail.
+
+**Burned vested coin existance** &emsp; whether the burned coin
+$\t{BCoin}$ matches the vesting configuration record one. If no then
+fail.
+
+Let there be a prover auxiliary witness inputs:
+$$ \begin{aligned}
+  VAx &∈ 𝔽ₚ \\
+  VPK &∈ 𝔽ₚ \\
+  Sx &∈ 𝔽ₚ \\
+  τ &∈ 𝔽ₚ \\
+  T &∈ ℕ₆₄ \\
+  C &∈ ℕ₆₄ \\
+  S &∈ ℕ₆₄ \\
+  E &∈ ℕ₆₄ \\
+  V &∈ ℕ₆₄ \\
+  b_\t{VC} &∈ 𝔽ₚ
+  Bv &∈ ℕ₆₄ \\
+  b_\t{BCoin} &∈ 𝔽ₚ \\
+  x_c &∈ 𝔽ₚ
+\end{aligned} $$
+
+Attach a proof $π$ such that the following relations hold:
+
+**Proof of vesting authority public key ownership** &emsp; $\t{VAPK} =
+\t{DerivePubKey}(VAx)$.
+
+**Proof of shared secret public key ownership** &emsp; $\t{SPK} =
+\t{DerivePubKey}(Sx)$.
+
+**Vesting configuration bulla integrity** &emsp; $ℬ =
+\t{Bulla}_\t{VC}(\mathcal{X}(p.\t{VAPK}), \mathcal{Y}(p.\t{VAPK}),
+\mathcal{X}(p.\t{VPK}), \mathcal{Y}(p.\t{VPK}),
+\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}), t, T, C, S, E, V,
+b_\t{VC})$
+
+**Proof of forfeit amount correctness** &emsp; $ForfeitValue = T - Bv$
+
+Verify the child `Money::transfer()` call correctnes:
+
+**Burned vested coin integrity** &emsp; $BCoin =
+\t{PoseidonHash}(\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}),
+ForfeitValue, t, \t{CID}_\t{V}, \t{SH}_\t{V}, ℬ, b_\t{Coin})$
+
+**Burned vested coin nullifier integrity** &emsp; $\cN =
+\t{PoseidonHash}(x_c, BCoin)$
+
+**Minted coin integrity** &emsp; $Coin =
+\t{PoseidonHash}(\mathcal{X}(p.\t{SPK}), \mathcal{Y}(p.\t{SPK}),
+ForfeitValue, t, \t{CID}_\t{V}, \t{SH}_\t{V}, ℬ, b_\t{Coin})$
+
+### Signatures
+
+There should be a single signature attached, which uses
+$\t{SPK}$ as the signature public key.
+
+[1]: ../money/model.md#coin
+[2]: ../../crypto-schemes.md#pallas-and-vesta
+[3]: ../../crypto-schemes.md#verifiable-in-band-secret-distribution

+ 44 - 63
doc/src/spec/contract/vesting/vesting.md

@@ -1,67 +1,48 @@
 # Vesting
 
-## Abstract
-
-We want to create a fully anonymous vesting contract, in which all the vesting information is private.
-What we need, is a vesting authority, which initially submits coins to be vested, along with the vesting
-configuration. When this happens, all input coins, which must be for the same token, get burned, and a new
-coin is minted for the vested public key, which uses the spend hook of the vesting contract, effectivelly
-becoming usable only withing the vesting contract context. After some time has passed, the vestee can
-withdraw some coins, which is done by burning the existing vested coin, and creates two output coins;
-one representing the remaining balance using the spend hook of the vesting contract and a second one
-which will be a normal coin for a withdrawal address(DAOs can be recipients too).
-
-The vesting authority must also be able to forfeit the configured vesting. There is a limitation though;
-the vested coin can only be controlled by a single address. To overcome this, when the vesting authority
-creates the vested coin, instead of using the recipients actual address, it generates a new random one,
-which is shared with the vestee(in a safe off-chain manner), so the coin can be controlled by both parties.
-When the vestee withdraws some funds, the new remaining balance token must use the same shared secret key.
-We don't care if that becomes a zero value coin, since it won't be usable anymore, and we want all our
-outputs to look the same, so the final withdrawl cannot be tracked.
-
-## Vesting configuration
-
-The vesting contract uses 1 day block windows as its time measurement, similar to the DAO contract.
-
-The configuration structure contains the following:
-    1. auth_public_x: The vesting autority public key X coord
-    2. auth_public_y: The vesting autority public key Y coord
-    3. shared_public_x: The shared vestee public key X coord
-    4. shared_public_y: The shared vestee public key Y coord
-    5. cliff: Amount unlocked at the cliff timestamp.
-    6. cliff_window: Vesting contract cliff block window.
-    7. start_window: Block window when the tokens start vesting.
-    8. end_window: Block window when all the tokens are fully vested.
-
-The above information get hashed by poseidon to produce the VestingBulla, which is used as the on-chain
-identifier of this specific configuration.
+```
+status: draft
+```
 
-## Contract calls
-
-TODO: describe all the checks for each call
-
-### Vest
-Vesting authority submits a vesting configuration on-chain, burns the to-be-vested input coins and mints
-a new coin with their total amount for the shared secret address, using the contracts' spend-hook.
-
-### Withdraw
-This call is responsible to define the available to withdraw amount, along with checking the first output
-correctly represents the shared secret and uses contract spend-hook. In this call, input coin value
-commitment must match the addition of the output coin value commitments. Also we check the next call is a
-normal money transfer call, which executes the actual burn and mint functions.
-
-### ExecWithdraw
-This is an overlay function, acting as the parent of a Withdraw and money Transfer calls combination, to
-bound them together into a single atomic action, and define the input spendhook that must be used in the
-transfer call.
-
-### Forfeit
-With this call, the vest autority is able to forfeit a specific vesting, by removing the configuration,
-burning the existing vest coin and mint a new one to a recipient address, using a normal money transfer.
-Input and output coin values must be identical.
-
-### ExecForfeit
-This is an overlay function, acting as the parent of a Forfeit and money Transfer calls combination, to
-bound them together into a single atomic action, and define the input spendhook that must be used in the
-transfer call.
+## Abstract
 
+This contract implements fully anonymous vesting, in which all the
+vesting information is private. Anyone can become a vesting authority,
+submitting coins to-be-vested for another user(or a DAO), the vestee.
+After some time has passed, the vestee can withdraw a chunk of the
+vested coin value. The vesting authority is also able to forfeit a
+vesting at any time, retrieving the remaining vested coin balance.
+
+- [Concepts](concepts.md)
+- [Model](model.md)
+- [Scheme](scheme.md)
+
+> Open questions:
+> 1. Do we need a separate cliff time? If its set thats the start time
+> so no real need to keep them both we can assume start == cliff.
+> 2. Is using the shared key for signatures safe and needed?
+> 3. Should vesting configurations be grouped by authority so is easier
+> UX to manage them?
+> 4. Is the vested coin encryption verification formula correct?
+> 5. Do we need to check both coins in withdraw transfer in the proof or
+> its fine since transfer itself enforces them?
+> 6. Vesting requires 1-1 vested coin to config matching, which means
+> vested coin is trackable as they are used during the vesting process.
+> Does that break any anonymity properties? Withdrawed coins cannot be
+> tracked, just the vested coin.
+> 7. We need to figure out a way to handle withdrawls after end
+> blockwindow has passed. We can use `cond_select` where both prover
+> and verifier pass the condition checl `current >= end` and in the
+> proof we pick current blockwindow or end blockwindow based on that.
+> But this require the verifier to know the end blockwindow, unless we
+> find a way the condition check can be done without revealing it.
+> Another option is to have an explicit `WithdrawAfterEnd` to withdraw
+> remaining balance after end blockwindow has passed. We already have
+> the metadata leak of ending tracking assumption, so perhaps its
+> worthy to sacrifice it.
+> 8. Withdrawl calcs correctness? They can also be simplified further
+> for proof optimization.
+> 9. All calls use the same parameters. Unless we need something in any
+> of them they will be the same structure in the final code.
+> 10. Do we need to check both coins in forfeit transfer in the proof or
+> its fine since transfer itself enforces them?