# Actor Spec: PaymentChannel
[Back to Master Tracking Doc](https://hackmd.io/LOZjAsz-THelSD5lWqSVlw)
## Contents
[TOC]
## At a Glance
The PaymentChannel actor allows two parties to establish an off-chain payment channel. This channel is only one directional from the party that sends the funds to the party that receives the funds.
* Both parties may engage in microtransactions off-chain by exchanging signed Vouchers.
* Vouchers may be submitted to the PaymentChannel instance by either party. Submitted Vouchers update the on-chain state of the PaymentChannel.
* Either party may call `Settle` to begin the PaymentChannel's settling period.
* Once the settling period ends, either party may call `Collect` to finalize the PaymentChannel's on-chain state, sending the appropriate amounts to each party and terminating the actor itself.
**Actor Type:**
- Instanced
**Exported Methods:**
1. Constructor
2. UpdateChannelState
3. Settle
4. Collect
## State
```go=
type State struct {
From addr.Address
To addr.Address
ToSend abi.TokenAmount
SettlingAt abi.ChainEpoch
MinSettleHeight abi.ChainEpoch
LaneStates []*LaneState
}
```
**`From`**: The owner of the channel. Expected to send microtransactions to `To` off-chain.
* Notes:
* `From` is expected to fund the PaymentChannel with a token amount.
* Invariants:
* `From` is an ID address
* `From` is an Account actor
**`To`**: The beneficiary who receives payments off-chain in the form of signed vouchers.
* Notes:
* `To` is expected to validate that the `CurrentBalance` of the PaymentChannel actor on-chain meets or exceeds the value of the vouchers being signed off-chain.
* Invariants:
* `To` is an ID address
* `To` is an Account actor
**`ToSend`**: The token amount successfully redeemed by the highest-nonce voucher submitted to `UpdateChannelState`. Paid to `To` on `Collect`.
* Notes:
* Any remaining value will be sent to `From`.
* Invariants:
* `ToSend >= 0`
* `ToSend <= rt.CurrentBalance()`
**`SettlingAt`**: The epoch after which a call to `Collect` will send `ToSend` to `To`.
* Notes:
* Initially, `SettlingAt` is set to 0, denoting that the PaymentChannel is not currently settling.
* A nonzero value denotes that the PaymentChannel will settle at `SettlingAt`, at which point `Collect` can be called.
* Invariants:
* `SettlingAt >= 0`
**`MinSettleHeight`**: If set, denotes the minimum epoch at which the PaymentChannel can `Settle`.
* Notes:
* Can only be set via `UpdateChannelState`: both parties must agree to this value.
* Invariants:
* `MinSettleHeight >= 0`
**`LaneStates`**: A collection of "lanes" between the parties. Each lane keeps track of its latest-seen `Nonce` and total `Redeemed` amount.
* Invariants:
* `len(st.LaneStates) <= LaneLimit` (256)
#### LaneState
```go=
type LaneState struct {
ID uint64
Redeemed big.Int
Nonce uint64
}
```
**`ID`**: The lane's ID in `st.LaneStates`.
* Notes:
* Any valid `uint64` value may serve as an `ID`.
* A signed voucher specifies to which lane it applies via the field `sv.Lane`
**`Redeemed`**: The token amount successfully redeemed by the highest-nonce voucher associated with this lane.
* Notes:
* `Redeemed <= rt.CurrentBalance()`
* `Redeemed >= 0`
**`Nonce`**: The highest-seen nonce attributed to a voucher redeemed for this lane.
## Exported Methods
#### 1. Constructor
```go=
func (pca *Actor) Constructor(rt vmr.Runtime, params *ConstructorParams) *adt.EmptyValue
```
Initializes actor state with the resolved addresses of `params.From` and `params.To` as the PaymentChannel's parties.
**`params.From`** may be provided as address protocols SECP, BLS, or ID.
**`params.To`** may be provided as address protocols SECP, BLS, or ID.
##### Failure conditions
* `params.From` is not an Account actor
* `params.To` is not an Account actor
#### 2. UpdateChannelState
```go=
func (a Actor) UpdateChannelState(rt vmr.Runtime, params *UpdateChannelStateParams) *adt.EmptyValue
```
Allows either party to update the channel's state by providing a voucher signed by their counterparty.
Supports two primary operations:
* Lane creation: If the lane specified by `params.Sv.Lane` does not exist, it will be created.
* Up to 256 unique lanes may be exist in PaymentChannel before lane creation fails.
* Lanes are created one-at-a-time: a maximum of 1 lane will be created per call to `UpdateChannelState`
* On creation, the new lane is placed in `st.LaneStates` with the following values:
* `ID`: `params.Sv.Lane`
* `Redeemed`: `params.Sv.Amount`
* `Nonce`: `params.Sv.Nonce`
* Lane merges: The redemption of a voucher through `UpdateChannelState` is an implicit "merge" of the voucher's `params.Sv.Amount` into the lane's state. A merge updates the lane's `Redeemed` and `Nonce` fields.
* Additional merges may be specified through the optional field `params.Sv.Merges`. For each entry therein, a merge operation will be performed from `merge.Lane` into `params.Sv.Lane`.
* Each merged lane's `Redeemed` total is subtracted from `params.Sv.Amount`. The sum of these operations is added to `st.ToSend`.
##### Parameters
```go=
type UpdateChannelStateParams struct {
Sv SignedVoucher
Secret []byte
}
```
**`Sv`**: A voucher signed by either `st.From` or `st.To`
**`Secret`**: If the SignedVoucher has a SecretPreImage (`len(sv.SecretPreimage) > 0`), the hash of `Secret` must match it.
* Requirements:
* `len(Secret) <= MaxSecretSize` (256)
###### SignedVoucher
```go=
type SignedVoucher struct {
ChannelAddr addr.Address
TimeLockMin abi.ChainEpoch
TimeLockMax abi.ChainEpoch
SecretPreimage []byte
Extra *ModVerifyParams
Lane uint64
Nonce uint64
Amount big.Int
MinSettleHeight abi.ChainEpoch
Merges []Merge
Signature *crypto.Signature
}
```
**`ChannelAddr`**: The address of the PaymentChannel actor this SignedVoucher is valid for
* Requirements:
* `ChannelAddr == rt.Message().Receiver()`
**`TimeLockMin`**: Before epoch `TimeLockMin`, this voucher may not be redeemed.
* Notes:
* OPTIONAL. 0 by default.
* Requirements:
* `rt.CurrEpoch() < TimeLockMin`
**`TimeLockMax`**: After epoch `TimeLockMax`, this voucher may not be redeemed. If `TimeLockMax` is 0, this field is not checked.
* Notes:
* OPTIONAL. 0 by default.
* `TimeLockMin == TimeLockMax` implies a 1-epoch window in which the voucher may be redeemed
* Requirements:
* `TimeLockMax == 0 || rt.CurrEpoch() >= TimeLockMax`
**`SecretPreimage`**: If provided, `params.Secret` must be a valid preimage of `SecretPreimage`
* Notes:
* OPTIONAL. `nil` by default.
**`Extra`**: If provided, `Extra` defines an arbitrary Send that should succeed when provided some additional `Proof` by the Caller.
* Notes:
* OPTIONAL. `nil` by default.
* No value will be sent with this Send.
* See `ModVerifyParams` below for details on individual fields.
* Requirements:
* The Send must succeed (`ExitCode == 0`)
**`Lane`**: Specifies which lane the voucher will be redeemed for.
* Notes:
* If the lane does not exist within `st.LaneStates`, it will be created.
* A lane may not be created if there are already 256 lanes in the PaymentChannel.
**`Nonce`**: Prevents the redemption of old vouchers. `Nonce` is compared to the highest-seen nonce of the lane specified by `Lane`. The lane's `ls.Nonce` will be set to `Nonce`.
* Requirements:
* `ls.Nonce < Nonce`
**`Amount`**: The token amount this voucher may be redeemed for. The lane's `ls.Redeemed` field will be set to `Amount`.
* Notes:
* The sum of `Amount`, the lane's current `ls.Redeemed` amount, and any `ls.Redeemed` amounts from other lanes specified in `Merges` will be added to `st.ToSend`.
* Requirements:
* `Amount >= 0`
**`MinSettleHeight`**: If nonzero, may cause `UpdateChannelState` to modify the settling epoch.
* Notes:
* OPTIONAL. 0 by default.
* If the settling epoch has been set (`st.SettlingAt != 0`) AND `MinSettleHeight` specifies a greater epoch, the settling epoch is updated to `MinSettleHeight`.
* If `MinSettleHeight` specifies a greater epoch than the one currently recorded in `st.MinSettleHeight`, this state is updated.
* Requirements:
* `MinSettleHeight >= 0`
**`Merges`**: If provided, denotes a collection of other lanes that will be merged into the `Lane` specified by the voucher.
* Notes:
* OPTIONAL. `nil` by default.
* See `Merge` below.
**`Signature`**: A signature over `sv.SigningBytes`, signed by the counterparty to the Caller.
* Notes:
* If Caller is `st.From`, the signature must be from `st.To`
* If Caller is `st.To`, the signature must be from `st.From`
* Requirements:
* `Signature != nil`
* Must be a valid signature as determined by `rt.Syscalls().VerifySignature`
###### ModVerifyParams
```go=
type ModVerifyParams struct {
Actor addr.Address
Method abi.MethodNum
Params []byte
}
```
**`Actor`**: The actor to which a Send will be made, denoting extra verification.
**`Method`**: The MethodNum of the actor to invoke.
**`Params`**: The data provided as parameters to the method invocation.
###### Merge
```go=
type Merge struct {
Lane uint64
Nonce uint64
}
```
**`Lane`**: Which lane will be merged into the lane specified by the voucher (`sv.Lane`).
* Requirements:
* `Lane` must exist in `st.LaneStates`
* `Lane != sv.Lane`
**`Nonce`**: Compared to the highest-seen nonce of the merging lane. The lane's nonce is updated to this value.
* Requirements:
* `Nonce` must be greater than the current nonce of the merging lane.
##### Failure conditions
* Caller is not `st.From` or `st.To`
* `sv.Signature == nil`
* `st.SettlingAt != 0 && rt.CurrEpoch >= st.SettlingAt`
* `len(params.Secret) > MaxSecretSize` (256)
* SignedVoucher unable to be serialized via `SigningBytes`
* Signature verification fails (via `rt.Syscalls().VerifySignature`)
* SignedVoucher is not valid for this PaymentChannel (`rt.Message().Receiver() != sv.ChannelAddr`)
* `rt.CurrEpoch() < sv.TimeLockMin`
* `sv.TimeLockMax != 0 && rt.CurrEpoch() > sv.TimeLockMax`
* `sv.Amount < 0`
* `len(sv.SecretPreimage) != 0` AND hashed `params.Secret` does not match
* `sv.Extra != nil` AND external validation fails
* `sv.Lane` specifies a lane that does not exist in `st.LaneStates` AND `len(st.LaneStates) >= 256`
* `ls.Nonce >= sv.Nonce`
* For any provided Merge:
* `merge.Lane == sv.Lane`
* `merge.Lane` does not exist in `st.LaneStates`
* Nonce specified by `merge.Lane` LaneState is greater than or equal to nonce specified by `merge.Nonce`
* Updated `st.ToSend` balance would be negative
* Updated `st.ToSend` balance would be greater than the current balance of the PaymentChannel
#### 3. Settle
```go=
func (pca Actor) Settle(rt vmr.Runtime, _ *adt.EmptyValue) *adt.EmptyValue
```
Sets `st.SettlingAt`, which is the epoch where either party may call `Collect`. This may only be called once.
* `st.SettlingAt` is set to the maximum value between `rt.CurrEpoch() + SettleDelay` and `st.MinSettleHeight`
Once the channel has settled (`CurrEpoch == st.SettlingAt`), further updates to the channel are prohibited.
##### Failure conditions
* Caller is not `st.From` or `st.To`
* `Settle` has already been called (`st.SettlingAt != 0`)
#### 4. Collect
```go=
func (pca Actor) Collect(rt vmr.Runtime, _ *adt.EmptyValue) *adt.EmptyValue
```
At or after the settling epoch, allows either party to collect the amount redeemed so far.
* `st.ToSend` is sent to `st.To`
* The PaymentChannel actor is deleted via `rt.DeleteActor`, with `st.From` supplied as the beneficiary of the remaining funds.
##### Failure conditions
* Caller is not `st.From` or `st.To`
* `st.SettlingAt == 0`, denoting that `Settle` has not been called yet
* `rt.CurrEpoch() < st.SettlingAt`, denoting that the settling epoch has not been reached
* The Send to `st.To` fails
* `rt.DeleteActor(st.From)` fails because `st.From` does not exist
## Open Questions
* UpdateChannelState: Does `SigningBytes()` add additional salt, domain separators, or other information to ensure that signed vouchers are unique in respect to both the payment channel AND the specific permutation of provided values?
* UpdateChannelState: Does `Syscalls().VerifySignature()` resolve the `signer` to a BLS/SECP address?
* UpdateChannelState: Should `SignedVoucher.ChannelAddr` use the PaymentChannel's ACTOR address for re-org protection?
* Collect: Could `st.From` cause the first `Send` to fail in any way outside of the actor being underfunded already?