Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,50 @@ breaking changes. Cyze is beta, unaudited software (see the README).
- **Zcash community votes:** the coinholder rounds run through Shielded Vote,
with **Decide together** to turn a round's proposals into group polls.
Casting the group's vote comes later.
- Records from a newer version of Cyze are kept and skipped, so members on
different versions stay in sync.
- **Payees:** a shared list of the addresses a group pays, by name.
- Pick one in the send form, or save a typed address with **Save as a group
payee**.
- Approvers see the payee's name, looked up in their own app from the
address the transaction verifiably pays.
- Only the member who added a payee can change or remove it, and no two
payees share a name or an address.
- **Batch payments:** up to 20 payments in one transaction, approved once.
- **Pay several at once** on the send form, with rows to fill or **Paste a
list** (address or payee name, amount, memo per line).
- Each approver's app checks that the transaction makes exactly the payments
described, in any order.
- Activity shows a batch as its payments.
- **Pay if agreed:** a group poll can propose payments, answered **Pay** or
**Don't pay**.
- Once Pay is agreed, the member who proposed it sends them with **Send
payment**, built from the poll itself.
- Each approver's app checks the request against its own copy of the poll:
it refuses one sent by another member, one that doesn't make exactly the
proposed payments, or one already paid, and shows whether the group
agreed.
- The poll then shows **Paid**, and can't be sent again.
- **Group rules**, adopted by poll (**Rules** on Home, then **Propose rules**):
- **Pay only trusted payees.** A payee is trusted once as many members trust
its address as a payment needs approvals.
- **Larger payments need more approvals**, for payments over an amount
together in one transaction.
- **Small payments can be approved automatically:** within a spending limit
(counting everything the wallet sent in the period), members who turn it
on let their app approve payments to trusted payees by itself, and it
tells them.
- **Larger payments wait for vetoes:** they're announced in a payment poll
(**Announce it** on the send form) and can be sent once the wait has
passed with no member choosing Don't pay. Each app counts the wait from
when it received the announcement.
- The sender's app checks the rules before asking anyone, and each
approver's app checks them again and refuses a payment that breaks them.
Approvers see which rules a request met.
- **Reasons:** say what a payment is for, for the group only.
- Approvers see it with the request, attributed to the member who asked.
- Once sent, every member's **Activity** shows it. Any member can add
theirs to any transaction, received ones too.
- **Approval deadlines.** A payment keeps the standard expiry (about 50
minutes), so it looks like any other wallet's on-chain.
- The sender sees how long approvers will have, then when approvals are
Expand All @@ -39,6 +83,11 @@ breaking changes. Cyze is beta, unaudited software (see the README).
- The memo-based coinholder vote (Vote Cast Memo v1), replaced by Votes.

### Fixed
- A signing request whose transaction didn't fit one message to an approver
failed with "cryptography error from snow: input error". The limit didn't
count the context being hex-encoded, so a send spending many notes could hit
it. Cyze now sizes the request exactly and, when it can't fit, says so before
anyone is asked.
- A send that a lock or restart cut off showed "in progress" forever. It now
says it ended and offers the right retry.
- A failed payment was hidden until Send was opened again. It now stays on Home
Expand Down
13 changes: 8 additions & 5 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ When the organizer makes their server reachable through a **Cloudflare tunnel**
or **Tailscale**, that provider carries the (still end-to-end encrypted)
traffic and sees the same kind of connection details.

### Polls and community votes

- **Group polls** travel through your group's coordination server like
everything else members send each other: end-to-end encrypted, so the server
sees only that members exchanged messages, not the questions or answers.
### Polls, payees, reasons and community votes

- **Group polls, payees and payment reasons** travel through your group's
coordination server like everything else members send each other: end-to-end
encrypted, so the server sees only that members exchanged messages, not the
questions, answers, names, addresses or reasons. Every member of the group
sees them all; they're kept encrypted on each member's device, and none of
them goes on chain.
- **Zcash community votes**: to show what's being voted on, the app reads the
public round list and results from ValarGroup's voting config at
`voting.valargroup.org` and the vote servers it lists. The requests are the
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,21 @@ The app has five places: **Home**, **Approvals**, **Votes**, **Groups** and
- **Sending takes two steps:** enter the payment, then review it and choose
who approves.
- **Send all** pays everything, with the fee taken out of the amount.
- **Pay several at once:** up to 20 payments in one transaction, approved
once. Enter them one by one or paste a list.
- **Transparent addresses** are detected automatically, with a note that the
payment will be public.
- **Activity** lists payments with their memos and fees.
- **Payees:** the group keeps a shared list of the addresses it pays, by
name. Pick one when sending; approvers and the history show its name.
- **Pay if agreed:** a group poll can propose payments. Once the group
agrees, its author sends exactly those, and each approver's app checks the
transaction against the poll.
- **Rules:** pay only trusted payees, more approvals for larger payments, a
wait with veto before larger payments, and a spending limit within which
members' apps can approve by themselves, adopted by poll.
- **Reasons:** a payment can say what it's for. Approvers see it, and so
does every member's history. It never goes on chain.
- With several groups, a switcher at the top picks the one wallet the app
syncs and acts on.
- **A wallet that's always current.**
Expand Down Expand Up @@ -193,6 +205,19 @@ signing, an advanced option).
- **One approval per payment.** A payment that spends several notes needs one
approval; its other rounds are approved once they verify as the same
transaction.
- **Group rules, enforced by every approver's app.** A group can adopt rules
by poll: pay only trusted payees (those as many members trust as a payment
needs), more approvals for larger payments, a wait before larger payments,
during which any member can veto them, and a spending limit within which
members who choose to can have their app approve payments to trusted payees
by itself. The sender's and each
approver's app refuse a payment that breaks them. With no contracts on
shielded funds, rules hold unless that many members act together, like the
wallet itself.
- **Names come from your own app.** A payment to one of the group's payees is
named from the approver's own copy of the list, by the address the
transaction verifiably pays. Only the member who added a payee can change
it. A reason for a payment is the sender's word, shown as theirs.
- **No unverified signing.** Wallet keys never sign a request without a
transaction attached, unless advanced options are on.
- **Nothing is at risk before approval.** Round-1 commitments don't depend on
Expand Down
61 changes: 61 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,56 @@ current build depends on them.
tailnet (explicitly public β€” would need the same loud warning as the
Cloudflare tunnel).

## Coordination (Safe-style features)

Zcash has no contracts for shielded funds, so these are rules each member's app
applies when it decides whether to sign: they hold unless a threshold of members
act together with modified apps, the trust the wallet already rests on. New
kinds of group record ride on `core/src/polls.rs`, whose older versions keep
and skip kinds they don't know.

- [x] **Shared payees** β€” `core/src/payees.rs`, `commands/payees.rs`,
`src/wallet/Payees.tsx`. Author-owned; approvers name a payment from their
own copy, by the verified address (`verify::address_forms`).
- [x] **Payment reasons** β€” `SigningContext.reason` for approvers, then a
`PaymentReason` record keyed by txid once sent; any member can add theirs.
- [ ] **Accounting export** β€” CSV of history with payees, reasons and signers.
- [ ] **Read-only access** β€” export the group's viewing key for an accountant.
- [x] **Batch payments** β€” `wallet::prepare_payments` (single sends are a batch
of one), `SigningContext.payments` matched as an unordered set by
`check_coordinator_claims`, `src/wallet/Batch.tsx`. Up to
`MAX_PAYMENTS` (20); the request is sized exactly against one frostd
message (`signing::signer_context_budget`) and refused at review when it
can't fit.
- [x] **Pay if agreed** β€” `Poll.payments` and a `PollPaid` record
(`core/src/polls.rs`); `wallet_send` with `poll_id` builds from the poll
(its author only, once agreed, once); approvers' `check_poll`
(`commands/signing.rs`) refuses another sender, other payments, or a
paid poll. Follow-up: let members who voted Pay have their app approve
it automatically, as the spending limit does for small payments.
- [x] **Group rules** β€” `core/src/rules.rs`, adopted by poll (`Poll.rules`,
`polls::rules_in_effect`); checked by `commands::rules::check` in the
sender's `wallet_send` (against its own verified draft) and the
approvers' gate.
- [x] **Trusted payees only** β€” `PayeeTrust` records; a payee is trusted once
threshold members trust its current address.
- [x] **Spending limits** β€” `GroupRules.limit` and
`rules::may_approve_automatically`; each member opts in
(`PrivateSettings.auto_approve`); `commands::rules::automatic_approval`
counts the wallet's history over the period (by blocks) plus this
device's in-flight automatic approvals, and only with a fresh sync.
- [x] **Delay with veto** β€” `GroupRules.delay`; announcements are payment
polls, sendable once the delay has passed since each app received them
(`GroupLog.received`, `PollView.announced_at`) with no Don't pay vote
(`commands::rules::poll_permits`).
- [x] **Tiered approvals** β€” `GroupRules.large`; approvers count the signers
committed in the signing package (`AwaitingApproval.signers`).
- [ ] **Change members or threshold** β€” a new group, then move the funds
(reusing the viewing-key move, `commands/viewing.rs`).
- [ ] **Share repair** β€” a member who lost their device gets a new share from
the others (FROST repairable shares), without moving funds.
- [ ] **Recurring payments** β€” scheduled payments that still need approval.

## Voting (protocol / coinholder governance)

- [ ] **Migrate to ValarGroup Shielded Vote (full rebuild; supersedes memo v1)** β€”
Expand Down Expand Up @@ -187,6 +237,17 @@ current build depends on them.

## Wallet (Zcash)

- [ ] **Record our own sends in the wallet** β€” Cyze builds sends as PCZTs and
broadcasts them itself, so the wallet db learns of them only by scanning:
as a balance change, without the fee or outputs (`sent_notes` stays
empty; compact blocks can't be decrypted with the OVK). History then
shows the fee inside the amount and no recipient. The sending device
fills these in from its saved send (`withWhatWasSent` in Activity.tsx).
Fix: `extract_and_store_transaction_from_pczt` at broadcast (the sender),
and for other members either enhancement (fetching full transactions,
which tells the server which are the group's) or the details in a group
record.

- [x] **Auto-sync polish** β€” the backend sync service keeps the active wallet
current, so Home no longer shows a permanent **Sync Now**: it offers
**Retry now** after a failed sync and **Restart** after a minute without
Expand Down
Loading
Loading