mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-11-12 18:43:53 +01:00
105 lines
6.3 KiB
Markdown
105 lines
6.3 KiB
Markdown
# Wallet contracts
|
|
|
|
Contracts use the same flow for standard sends and invoice transactions. Signing is kept
|
|
as an explicit step. Each side can check the slate it receives and its own contribution,
|
|
but not commitments added by the other side later in the flow.
|
|
|
|
A two-party contract is `new`, `sign`, `sign`. A self-spend is `new`, `sign`. There is no
|
|
separate `setup` command. Setup is done by `new`, or by the first `sign` when needed.
|
|
|
|
The owner API provides all four commands. The Rust foreign API also provides `new` and
|
|
`sign` for receiving contracts, but they are not exposed by the foreign JSON-RPC API. The
|
|
API does not require manual confirmation, so a wallet using it still needs to show the
|
|
transaction and ask the user before signing.
|
|
|
|
The CLI exchanges Slatepacks. The last `sign` broadcasts the transaction unless
|
|
`--no-broadcast` is used. `--outfile` overrides the output Slatepack file for `new`, `sign`
|
|
and `revoke`.
|
|
|
|
## Amounts and fees
|
|
|
|
`--send` and `--receive` are the amount being transferred, before each side pays its own
|
|
fee. The sender spends the amount plus its fee. The receiver gets the amount minus its
|
|
fee. Without either option, `contract sign` reads both from the first slate. Each side pays
|
|
for its own inputs and outputs and a rounded-up share of the kernel fee.
|
|
|
|
CLI amounts are human readable. Values passed to the API, including `make_outputs`, are in
|
|
nanogrin. Outputs requested with `make_outputs` are added together with the output needed
|
|
to balance that side of the transaction.
|
|
|
|
Payjoin is used by default. A receiver adds an input when one is available. An empty wallet
|
|
can still receive; the fee is then taken from the received output. `--no-payjoin` prevents
|
|
the receiver from adding an input and cannot be used together with `--use-inputs`. Pass one
|
|
or more comma-separated output commitments to `--use-inputs` to select specific payjoin inputs.
|
|
|
|
Inputs and outputs are normally picked when signing. `--add-outputs` picks and locks them
|
|
during `new`. Prepared outputs appear as unconfirmed in the wallet, but are only added to
|
|
the slate when signing. Using `--use-inputs` or `--make-outputs` during `new` does the same.
|
|
Each party chooses `--min_conf` when it first joins and cannot change it later. The same limit
|
|
is used for the fee estimate, so any required inputs need enough confirmations at that point.
|
|
A value of `0` allows unconfirmed non-coinbase outputs. Open contracts do not reserve funds,
|
|
so a late-locked contract can fail if another transaction spends the available outputs first.
|
|
Signing then returns `NotEnoughFunds`; revoke and recreate the contract, or use `--add-outputs`
|
|
when creating it to reserve inputs.
|
|
|
|
`contract new --ttl_blocks N` stops contract signing after `N` blocks. Finalized transactions
|
|
can still be posted afterward.
|
|
|
|
`--fee_rate N` uses `N` nanogrin per weight unit for this wallet's fee contribution. Each
|
|
wallet chooses its rate when it first joins. Without it, the wallet uses `accept_fee_base`
|
|
(500000 by default). The wallet only finalizes when the combined fee meets that minimum. If it
|
|
does not, revoke the contract and create a new one.
|
|
|
|
Each side's account is fixed when it first joins the contract. Changing the active account
|
|
later does not affect setup or signing; they use the account stored in the context.
|
|
Encrypted Slatepacks still need their account selected with `--account`; the error names it.
|
|
|
|
## View and revoke
|
|
|
|
`view` reads a slate or Slatepack and shows its inputs and outputs when present, fees,
|
|
transfer amount and the resulting change to this wallet when known. It also reports whether
|
|
the Slatepack was encrypted for this wallet, whether the local transaction is confirmed,
|
|
and whether the slate contains unexpected inputs or outputs from this wallet. This last
|
|
check is reported as unknown after the private context has been removed, when input features
|
|
are missing, or when the slate does not contain a transaction. `view` cannot find a contract
|
|
by id.
|
|
|
|
An encrypted Slatepack can have several recipients. The encryption status only shows that
|
|
this wallet could decrypt it.
|
|
|
|
`revoke` cancels the local transaction. When the wallet added an input, it returns a
|
|
self-spend of that input. The caller still has to post it, and either transaction can win
|
|
if the original is already in the mempool. When the wallet added no input there is no
|
|
replacement transaction. The replacement does not use a higher fee. An interrupted
|
|
`revoke` can be run again. Nodes do not currently replace a mempool transaction with the
|
|
revoke transaction. Transaction ids belong to an account, so the CLI uses the
|
|
account selected with `--account`.
|
|
|
|
## Current limitations
|
|
|
|
* Only one or two participants are supported. Larger contracts remain disabled because of
|
|
the [known multi-party attack](https://forum.grin.mw/t/grin-wallet-contract-prototype/9745/18)
|
|
* Early payment proofs are available for contracts through the API and CLI. Use `--proof-type`
|
|
and optionally `--memo` (up to 1024 bytes of UTF-8 text). The proof binds the memo's Blake2b hash
|
|
* `export_proof` and `verify_proof` also handle early proofs
|
|
* Invoice proofs work with SRS and RSR. Sender-nonce proofs only work with RSR. Both need
|
|
experimental Slate V5; see
|
|
[Early Payment Proofs](https://github.com/mimblewimble/grin-rfcs/pull/70)
|
|
* Proof data is stored in the wallet database and cannot be restored from the seed
|
|
* There are no contract-specific history, lookup or transport commands
|
|
* If writing the signed transaction file fails, the wallet state has already been saved.
|
|
Cancelling the transaction releases the locked inputs
|
|
|
|
Implementation notes and remaining work are kept in
|
|
[`libwallet/src/contract/actions/README.md`](../libwallet/src/contract/actions/README.md).
|
|
|
|
## References
|
|
|
|
* [Contract prototype discussion](https://forum.grin.mw/t/grin-wallet-contract-prototype/9745)
|
|
* [Manual confirmation proposal](https://github.com/mimblewimble/grin-rfcs/pull/84) (open)
|
|
* [Early payment proofs proposal](https://github.com/mimblewimble/grin-rfcs/pull/70) (open)
|
|
* [RFC 0006: Payment Proofs](https://github.com/mimblewimble/grin-rfcs/blob/master/text/0006-payment-proofs.md)
|
|
* [RFC 0012: Compact Slates](https://github.com/mimblewimble/grin-rfcs/blob/master/text/0012-compact-slates.md)
|
|
* [RFC 0015: Slatepack](https://github.com/mimblewimble/grin-rfcs/blob/master/text/0015-slatepack.md)
|
|
* [RFC 0017: Fix Fees](https://github.com/mimblewimble/grin-rfcs/blob/master/text/0017-fix-fees.md)
|