Split docs into seperate files (#72)
This commit is contained in:
parent
d5eb18f557
commit
d5c949b9ad
110
README.md
110
README.md
@ -6,82 +6,64 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
User purchases a ticket, doesnt need any special conditions, indistinguishable
|
dcrvsp is a from scratch implementation of a Voting Service Provider (VSP) for
|
||||||
from solo ticket. User can then choose to use a VSP on a per-ticket basis. Once
|
the Decred network.
|
||||||
the ticket is mined, and ideally before it has matured, the user sends the
|
|
||||||
ticket details + fee to a VSP, and the VSP will take the fee and vote in return.
|
|
||||||
|
|
||||||
## Advantages
|
A VSP running dcrvsp can be used to vote on any ticket - tickets do not need to
|
||||||
|
be purchased with any special conditions such as dedicated outputs for paying
|
||||||
|
VSP fees. Fees are paid directly to the VSP with an independent on-chain
|
||||||
|
transaction.
|
||||||
|
|
||||||
### For Administrators
|
To use dcrvsp, ticket holders must prove ownership of their ticket with a
|
||||||
|
cryptographic signature, pay the fee requested by the VSP, and submit a private
|
||||||
|
key which enables the VSP to vote the ticket. Once this process is complete the
|
||||||
|
VSP will add the ticket to a pool of always-online voting wallets.
|
||||||
|
|
||||||
- bbolt db - no database admin required.
|
## Features
|
||||||
- Database is not used outside of dcrvsp server.
|
|
||||||
- No stakepoold.
|
|
||||||
- Client accountability.
|
|
||||||
- No need to use the same wallet seed on each voting wallet.
|
|
||||||
- Fees can change regularly - previously cached by wallet.
|
|
||||||
|
|
||||||
### For Users
|
- **API** - Tickets are registered with the VSP using a JSON HTTP API. For more
|
||||||
|
detail on the API and its usage, read [api.md](./docs/api.md)
|
||||||
|
|
||||||
- No redeem script to back up.
|
- **Web front-end** - A minimal, static, website providing pool stats.
|
||||||
- No registration required. No email.
|
|
||||||
- Multiple VSPs on a single ticket.
|
|
||||||
- Voting preferences per ticket.
|
|
||||||
- Server accountability.
|
|
||||||
- No address reuse.
|
|
||||||
- VSP fees are paid "out of band", rather than being included in the ticket
|
|
||||||
itself. This makes solo tickets and VSP tickets indistinguishable from
|
|
||||||
eachother, enabling VSP users to purchase tickets in the same anonymity set
|
|
||||||
as solo stakers.
|
|
||||||
|
|
||||||
## Design Decisions
|
- **Two-way accountability** - All dcrvsp requests must be signed with a private
|
||||||
|
key corresponding to the relevant ticket, and all dcrvsp responses are signed
|
||||||
|
by with a private key known only by the server. This enables both the client
|
||||||
|
and the server to prove to outside observers if their counterparty is
|
||||||
|
misbehaving. For more detail, and examples, read
|
||||||
|
[two-way-accountability.md](./docs/two-way-accountability.md).
|
||||||
|
|
||||||
- [gin-gonic](https://github.com/gin-gonic/gin) webserver.
|
- **Dynamic fees** - Clients must request a new fee address and amount for every
|
||||||
- Success responses use HTTP status 200 and a JSON encoded body.
|
ticket. When these are given to a client, there is an associated expiry
|
||||||
- Error responses use either HTTP status 500 or 400, and a JSON encoded error
|
period. If the fee is not paid in this period, the client must request a new
|
||||||
in the body (eg. `{"error":"Description"}')
|
fee. This enables the VSP admin to change their fee as often as they like.
|
||||||
- [bbolt](https://github.com/etcd-io/bbolt) k/v database.
|
|
||||||
- Tickets are stored in a single bucket, using ticket hash as the key and a
|
## Implementation
|
||||||
json encoded representation of the ticket as the value.
|
|
||||||
- [wsrpc](https://github.com/jrick/wsrpc) for RPC communication between dcrvsp
|
dcrvsp is built and tested on go 1.13 and 1.14, making use of the following
|
||||||
|
libraries:
|
||||||
|
|
||||||
|
- [gin-gonic/gin](https://github.com/gin-gonic/gin) webserver.
|
||||||
|
|
||||||
|
- [etcd-io/bbolt](https://github.com/etcd-io/bbolt) k/v database.
|
||||||
|
|
||||||
|
- [jrick/wsrpc](https://github.com/jrick/wsrpc) for RPC communication with dcrd
|
||||||
and dcrwallet.
|
and dcrwallet.
|
||||||
|
|
||||||
## Architecture
|
## Deployment
|
||||||
|
|
||||||
- Single server running dcrvsp and dcrd. dcrd requires txindex so
|
- Single server running dcrvsp and dcrd. dcrd on this server is used for fishing
|
||||||
`getrawtransaction` can be used.
|
ticket details out of the chain, and for broadcasting and checking the status
|
||||||
- Multiple remote voting servers, each running dcrwallet and dcrd. dcrwallet
|
of fee transactions. `--txindex` is required so `getrawtransaction` can be
|
||||||
on these servers should be constantly unlocked and have voting enabled.
|
used.
|
||||||
|
|
||||||
## MVP Features
|
- A xpub key is provided to dcrvsp via config. dcrvsp will use this key to
|
||||||
|
derive a new addresses for each fee payments. It is recommended to export an
|
||||||
|
xpub from a cold wallet which is not a part of the dcrvsp deployment.
|
||||||
|
|
||||||
- When dcrvsp is started for the first time, it generates a ed25519 keypair and
|
- Multiple remote voting servers, each running dcrwallet and dcrd. dcrwallet on
|
||||||
stores it in the database. This key is used to sign all API responses, and the
|
these servers should be constantly unlocked and have voting enabled. Three
|
||||||
signature is included in the response header `VSP-Server-Signature`. Error responses
|
voting servers in different physical locations are recommended for production.
|
||||||
are not signed.
|
|
||||||
- Every client request which references a ticket should include a HTTP header
|
|
||||||
`VSP-Client-Signature`. The value of this header must be a signature of the
|
|
||||||
request body, signed with the commitment address of the referenced ticket.
|
|
||||||
- An xpub key is provided to dcrvsp via config. dcrvsp will use this key to
|
|
||||||
derive addresses for fee payments. A new address is generated for each fee.
|
|
||||||
- VSP API as described in [dcrstakepool #574](https://github.com/decred/dcrstakepool/issues/574)
|
|
||||||
- Request fee amount (`GET /fee`)
|
|
||||||
- Request fee address (`POST /feeaddress`)
|
|
||||||
- Pay fee (`POST /payFee`)
|
|
||||||
- Ticket status (`GET /ticketstatus`)
|
|
||||||
- Set voting preferences (`POST /setvotechoices`)
|
|
||||||
- A minimal, static, web front-end providing pool stats and basic connection
|
|
||||||
instructions.
|
|
||||||
- Fees have an expiry period. If the fee is not paid within this period, the
|
|
||||||
client must request a new fee. This enables the VSP to alter its fee rate.
|
|
||||||
|
|
||||||
## Future Features
|
|
||||||
|
|
||||||
- Write database backups to disk periodically.
|
|
||||||
- Backup over http.
|
|
||||||
- Status check API call as described in [dcrstakepool #628](https://github.com/decred/dcrstakepool/issues/628).
|
|
||||||
- Consistency checking across connected wallets.
|
|
||||||
|
|
||||||
## Backup
|
## Backup
|
||||||
|
|
||||||
|
|||||||
48
docs/ANN.md
Normal file
48
docs/ANN.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Announcement
|
||||||
|
|
||||||
|
## Advantages vs dcrstakepool
|
||||||
|
|
||||||
|
### For VSP Administrators
|
||||||
|
|
||||||
|
- An instance of bbolt db on the front-end server is used as the single source
|
||||||
|
of truth:
|
||||||
|
- bbolt does not have the sys admin overhead associated with maintaining a
|
||||||
|
MySQL database. The database will be automatically created and maintained
|
||||||
|
by dcrvsp.
|
||||||
|
- The bbolt database is only accessed by dcrvsp. There is no need to open
|
||||||
|
additional ports on your front-end server for the voting wallets to access
|
||||||
|
the database.
|
||||||
|
- Voting wallet servers require only dcrwallet and dcrd. There is no longer a
|
||||||
|
VSP binary (ie. stakepoold) running on voting servers.
|
||||||
|
- Voting servers no longer need dcrd to be running with `--txindex`.
|
||||||
|
- No need to use the same wallet seed on each voting wallet.
|
||||||
|
- A new fee address and amount are requested for each ticket:
|
||||||
|
- Fee addresses are never reused.
|
||||||
|
- Fee amount can be changed freely.
|
||||||
|
- No emails or personal information are held. No need to worry about GDPR et al.
|
||||||
|
|
||||||
|
### For VSP Users
|
||||||
|
|
||||||
|
- No redeem script to back up.
|
||||||
|
- No registration required - no email, no password, no CAPTCHA.
|
||||||
|
- Voting preferences can be set for each individual ticket.
|
||||||
|
- No address reuse.
|
||||||
|
- VSP fees are paid independently of the ticket purchase, rather than being
|
||||||
|
included in the ticket:
|
||||||
|
- Multiple VSPs can be used for a single ticket.
|
||||||
|
- Fees can be paid using funds from a mixed account.
|
||||||
|
- VSP users can purchase tickets in the same anonymity set at solo stakers.
|
||||||
|
|
||||||
|
### For the Decred Ecosystem
|
||||||
|
|
||||||
|
- Solo tickets and VSP tickets are indistinguishable on-chain.
|
||||||
|
- Clients and servers can hold eachother accountable for actions. This enables
|
||||||
|
users to prove if a VSP is misbehaving, and VSPs to defend themselves if they
|
||||||
|
are falsely accused.
|
||||||
|
|
||||||
|
## Disadvantages
|
||||||
|
|
||||||
|
- Front-end is more important than before.
|
||||||
|
- Front-end requires dcrd with `--txindex`.
|
||||||
|
- Failure cases
|
||||||
|
- fee tx doesnt broadcast
|
||||||
155
docs/api.md
Normal file
155
docs/api.md
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
# API
|
||||||
|
|
||||||
|
## General notes
|
||||||
|
|
||||||
|
- Success responses use HTTP status 200 and a JSON encoded body.
|
||||||
|
|
||||||
|
- Error responses use either HTTP status 500 or 400, and a JSON encoded error
|
||||||
|
in the body. For example `{"error":"Description"}`.
|
||||||
|
|
||||||
|
- Requests which reference specific tickets need to be properly signed as
|
||||||
|
described in [two-way-accountability.md](./two-way-accountability.md).
|
||||||
|
|
||||||
|
- Implementation of request and response types can be found in
|
||||||
|
[webapi/types.go](./webapi/types.go).
|
||||||
|
|
||||||
|
## Expected usage
|
||||||
|
|
||||||
|
### Get VSP public key
|
||||||
|
|
||||||
|
Clients should first retrieve the VSP's public key so they can check the
|
||||||
|
signature on later API responses. A VSP should never change their public key so
|
||||||
|
it can be requested once and cached indefinitely.
|
||||||
|
|
||||||
|
- `GET /api/pubkey`
|
||||||
|
|
||||||
|
No request body.
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509065,
|
||||||
|
"pubkey":"bLNwVVcda3LqRLv+m0J5sjd60+twjO/fuhcx8RUErDQ="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Register ticket
|
||||||
|
|
||||||
|
**Registering a ticket is a two step process. The VSP will not add a ticket to
|
||||||
|
its voting wallets unless both of these calls have succeeded.**
|
||||||
|
|
||||||
|
Request fee amount and address for a ticket. The fee amount is only valid until
|
||||||
|
the expiration time has passed.
|
||||||
|
|
||||||
|
- `POST /feeaddress`
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"tickethash":"484a68f7148e55d05f0b64a29fe7b148572cb5272d1ce2438cf15466d347f4f4"
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"feeaddress":"Tsfkn6k9AoYgVZRV6ZzcgmuVSgCdJQt9JY2",
|
||||||
|
"fee":0.001,
|
||||||
|
"expiration":1590563759,
|
||||||
|
"request": {"<Copy of request body>"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Provide the voting key for the ticket, voting preference, and a signed
|
||||||
|
transaction which pays the fee to the specified address. If the fee has expired,
|
||||||
|
this call will return an error and the client will need to request a new fee by
|
||||||
|
calling `/feeaddress` again. The VSP will not broadcast the fee transaction
|
||||||
|
until the ticket purchase has 6 confirmations, and it will not add the ticket to
|
||||||
|
its voting wallets until the fee transaction has 6 confirmations.
|
||||||
|
|
||||||
|
- `POST /payfee`
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"tickethash":"484a68f7148e55d05f0b64a29fe7b148572cb5272d1ce2438cf15466d347f4f4",
|
||||||
|
"feetx":"010000000125...737b266ffb9a93",
|
||||||
|
"votingkey":"PtWUJWhSXsM9ztPkdtH8REe91z7uoidX8dsMChJUZ2spagm7YvrNm",
|
||||||
|
"votechoices":{"headercommitments":"yes"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"request": {"<Copy of request body>"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Information requests
|
||||||
|
|
||||||
|
Clients can check the status of the server at any time.
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
Clients can check the status of a ticket at any time after calling
|
||||||
|
`/feeaddress`.
|
||||||
|
|
||||||
|
- `GET /ticketstatus`
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"tickethash":"484a68f7148e55d05f0b64a29fe7b148572cb5272d1ce2438cf15466d347f4f4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"status":"active",
|
||||||
|
"votechoices":{"headercommitments":"no"},
|
||||||
|
"request": {"<Copy of request body>"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update vote choices
|
||||||
|
|
||||||
|
Clients can update the voting preferences of their ticket at any time after
|
||||||
|
after calling `/payfee`.
|
||||||
|
|
||||||
|
- `POST /setvotechoices`
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"tickethash":"484a68f7148e55d05f0b64a29fe7b148572cb5272d1ce2438cf15466d347f4f4",
|
||||||
|
"votechoices":{"headercommitments":"no"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"timestamp":1590509066,
|
||||||
|
"votechoices":{"headercommitments":"no"},
|
||||||
|
"request": {"<Copy of request body>"}
|
||||||
|
}
|
||||||
|
```
|
||||||
15
docs/two-way-accountability.md
Normal file
15
docs/two-way-accountability.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Two-way Accountability
|
||||||
|
|
||||||
|
- When dcrvsp is started for the first time, it generates a ed25519 keypair and
|
||||||
|
stores it in the database. This key is used to sign all API responses, and the
|
||||||
|
signature is included in the response header `VSP-Server-Signature`.
|
||||||
|
|
||||||
|
- Every client request which references a ticket should include a HTTP header
|
||||||
|
`VSP-Client-Signature`. The value of this header must be a signature of the
|
||||||
|
request body, signed with the commitment address of the referenced ticket.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Server does not vote ticket
|
||||||
|
|
||||||
|
### Client denies changing their voting preferences
|
||||||
@ -25,6 +25,8 @@ func setVoteChoices(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Return an error if we dont have a FeeTx for this ticket yet.
|
||||||
|
|
||||||
var setVoteChoicesRequest SetVoteChoicesRequest
|
var setVoteChoicesRequest SetVoteChoicesRequest
|
||||||
if err := binding.JSON.BindBody(rawRequest, &setVoteChoicesRequest); err != nil {
|
if err := binding.JSON.BindBody(rawRequest, &setVoteChoicesRequest); err != nil {
|
||||||
log.Warnf("Bad setvotechoices request from %s: %v", c.ClientIP(), err)
|
log.Warnf("Bad setvotechoices request from %s: %v", c.ClientIP(), err)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user