Browse Source

Use Root Hash as censusID when creating a snapshot.

Add more authentication control.
Fix snapshot namespace issue.
Improve documentation.

Signed-off-by: p4u <p4u@dabax.net>
feature_chain_module
p4u 5 years ago
parent
commit
6551f598cf
4 changed files with 119 additions and 96 deletions
  1. +92
    -9
      cmd/censushttp/README.md
  2. +2
    -73
      service/README.md
  3. +18
    -7
      service/censusmanager.go
  4. +7
    -7
      tree/tree.go

+ 92
- 9
cmd/censushttp/README.md

@ -1,23 +1,106 @@
# censusService
Reference implementation of a voting census service running on the Vocdoni platform
## Census HTTP service ## Census HTTP service
Reference implementation of a voting census service running on the Vocdoni platform
#### Compile #### Compile
In a GO ready environment:
``` ```
go get github.com/vocdoni/censusService
go build -o httpService http_census_service.go
go get -u github.com/vocdoni/dvote-census
go build -o censusHttpService github.com/vocdoni/dvote-census/cmd/censushttp
``` ```
#### Usage #### Usage
`./censusHttpService <port> [publicKey]`
Example:
``` ```
./httpService 1500
./censusHttpService 1500
2018/12/17 09:54:20 Starting process HTTP service on port 1500 2018/12/17 09:54:20 Starting process HTTP service on port 1500
2018/12/17 09:54:20 Starting server in http mode 2018/12/17 09:54:20 Starting server in http mode
``` ```
#### add claims
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/addClaim
{"error":false,"response":""}
```
If public key authentication enabled, `signature` field is required using Nancl signature.
The signed message is expected to be a concatenation of the following fields: `censusID, claimData, timeStamp`
```
curl -d '{"censusID":"GoT_Favorite",
"claimData":"Jon Snow",
"timeStamp":"1547814675",
"signature":"a117c4ce12b29090884112ffe57e664f007e7ef142a1679996e2d34fd2b852fe76966e47932f1e9d3a54610d0f361383afe2d9aab096e15d136c236abb0a0d0e"}' http://localhost:1500/addClaim
{"error":false,"response":""}
```
#### generate proof
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/genProof
{"error":false,"response":"0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}
```
#### check proof
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x0000000000000000000000000000000000000000000000000000000000000000000123"}' http://localhost:1500/checkProof
{"error":false,"response":"invalid"}
```
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}' http://localhost:1500/checkProof
{"error":false,"response":"valid"}
```
#### make snapshot
Snapshots are static and unmutable copies of a specific census
```
curl -d '{"censusID":"GoT_Favorite"}' http://localhost:1500/snapshot
{"error":false,"response":"0x8647692e073a10980d821764c65ca3fddbc606bb936f9812a7a806bfa97df152"}
```
The name for the snapshot is "0x8647692e073a10980d821764c65ca3fddbc606bb936f9812a7a806bfa97df152" which represents the Root Hash.
Now you can use it as censusID for checkProof, getRoot, genProof and dump. But addClaim is not longer allowed.
#### dump
Dump contents of a specific censusID (values)
```
curl -d '{"censusID":"GoT_Favorite"}' http://localhost:1500/dump
{"error":false,"response":"[\"Tyrion\",\"Jon Snow\"]"}
```
##### add claims ##### add claims
``` ```
@ -33,19 +116,19 @@ curl -d '{"processID":"GoT_Favorite","claimData":"Tyrion"}' http://localhost:150
##### generate proof ##### generate proof
``` ```
curl -d '{"processID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/genProof
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/genProof
{"error":false,"response":"0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"} {"error":false,"response":"0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}
``` ```
##### check proof ##### check proof
``` ```
curl -d '{"processID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x0000000000000000000000000000000000000000000000000000000000000000000123"}' http://localhost:1500/checkProof
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x0000000000000000000000000000000000000000000000000000000000000000000123"}' http://localhost:1500/checkProof
{"error":false,"response":"invalid"} {"error":false,"response":"invalid"}
``` ```
``` ```
curl -d '{"processID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}' http://localhost:1500/checkProof
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}' http://localhost:1500/checkProof
{"error":false,"response":"valid"} {"error":false,"response":"valid"}
``` ```

+ 2
- 73
service/README.md

@ -1,6 +1,6 @@
## dvot-process http service
## dvot-census http service library
#### start http server
#### How to use it
``` ```
processHttp.T.Init() processHttp.T.Init()
@ -13,74 +13,3 @@ To enable authentication (using pubKey signature):
pubK := "39f54ce5293520b689f6658ea7f3401f4ff931fa3d90dea21ff901cdf82bb8aa" pubK := "39f54ce5293520b689f6658ea7f3401f4ff931fa3d90dea21ff901cdf82bb8aa"
processHttp.Listen(1500, "http", pubK) processHttp.Listen(1500, "http", pubK)
``` ```
#### add claims
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/addClaim
{"error":false,"response":""}
```
```
curl -d '{"censusID":"GoT_Favorite",
"claimData":"Jon Snow",
"timeStamp":"1547814675",
"signature":"a117c4ce12b29090884112ffe57e664f007e7ef142a1679996e2d34fd2b852fe76966e47932f1e9d3a54610d0f361383afe2d9aab096e15d136c236abb0a0d0e"}' http://localhost:1500/addClaim
{"error":false,"response":""}
```
The signature message is a concatenation of the following strings: `censusID, claimData, timeStamp`
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Tyrion"}' http://localhost:1500/addClaim
{"error":false,"response":""}
```
#### generate proof
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/genProof
{"error":false,"response":"0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}
```
#### check proof
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x0000000000000000000000000000000000000000000000000000000000000000000123"}' http://localhost:1500/checkProof
{"error":false,"response":"invalid"}
```
```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow", "proofData": "0x000000000000000000000000000000000000000000000000000000000000000352f3ca2aaf635ec2ae4452f6a65be7bca72678287a8bb08ad4babfcccd76c2fef1aac7675261bf6d12c746fb7907beea6d1f1635af93ba931eec0c6a747ecc37"}' http://localhost:1500/checkProof
{"error":false,"response":"valid"}
```
#### make snapshot
Snapshots are static and unmutable copies of a specific census
```
curl -d '{"censusID":"GoT_Favorite"}' http://localhost:1500/snapshot
{"error":false,"response":"snaphost.GoT_Favorite.1548169813"}
```
The name for the snapshot is "snaphost.GoT_Favorite.1548169813"
Now you can use it as censusID for checkProof, genProof and dump. But addClaim is not longer allowed.
#### dump
Dump contents of a specific censusID (values)
```
curl -d '{"censusID":"GoT_Favorite"}' http://localhost:1500/dump
{"error":false,"response":"[\"Tyrion\",\"Jon Snow\"]"}
```

+ 18
- 7
service/censusmanager.go

@ -6,6 +6,7 @@ import (
"log" "log"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/vocdoni/dvote-census/tree" "github.com/vocdoni/dvote-census/tree"
@ -84,8 +85,8 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
} }
// Process data // Process data
log.Printf("Received: %s,%s,%s,%s,%s", c.CensusID, c.ClaimData, c.ProofData,
c.TimeStamp, c.Signature)
log.Printf("Received censusID:{%s} claimData:{%s} proofData:{%s} timeStamp:{%s} signature:{%s}\n",
c.CensusID, c.ClaimData, c.ProofData, c.TimeStamp, c.Signature)
resp.Error = false resp.Error = false
resp.Response = "" resp.Response = ""
@ -108,7 +109,12 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
if op == "add" { if op == "add" {
msg := fmt.Sprintf("%s%s%s", c.CensusID, c.ClaimData, c.TimeStamp) msg := fmt.Sprintf("%s%s%s", c.CensusID, c.ClaimData, c.TimeStamp)
if auth := checkAuth(c.TimeStamp, c.Signature, msg); auth { if auth := checkAuth(c.TimeStamp, c.Signature, msg); auth {
err = T.AddClaim([]byte(c.ClaimData))
if strings.HasPrefix(c.CensusID, "0x") {
resp.Error = true
resp.Response = "add claim to snapshot is not allowed"
} else {
err = T.AddClaim([]byte(c.ClaimData))
}
} else { } else {
resp.Error = true resp.Error = true
resp.Response = "invalid authentication" resp.Response = "invalid authentication"
@ -142,12 +148,17 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
if op == "snapshot" { if op == "snapshot" {
msg := fmt.Sprintf("%s%s%s", c.CensusID, c.ClaimData, c.TimeStamp) msg := fmt.Sprintf("%s%s%s", c.CensusID, c.ClaimData, c.TimeStamp)
if auth := checkAuth(c.TimeStamp, c.Signature, msg); auth { if auth := checkAuth(c.TimeStamp, c.Signature, msg); auth {
snapshotNamespace, err := T.Snapshot()
if err != nil {
if strings.HasPrefix(c.CensusID, "0x") {
resp.Error = true resp.Error = true
resp.Response = fmt.Sprint(err)
resp.Response = "snapshot an snapshot makes no sense"
} else { } else {
resp.Response = snapshotNamespace
snapshotNamespace, err := T.Snapshot()
if err != nil {
resp.Error = true
resp.Response = fmt.Sprint(err)
} else {
resp.Response = snapshotNamespace
}
} }
} else { } else {
resp.Error = true resp.Error = true

+ 7
- 7
tree/tree.go

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"os/user" "os/user"
"strings" "strings"
"time"
common3 "github.com/vocdoni/go-iden3/common" common3 "github.com/vocdoni/go-iden3/common"
mkcore "github.com/vocdoni/go-iden3/core" mkcore "github.com/vocdoni/go-iden3/core"
@ -47,7 +46,7 @@ func (t *Tree) Close() {
} }
func (t *Tree) AddClaim(data []byte) error { func (t *Tree) AddClaim(data []byte) error {
isSnapshot := strings.Contains(t.Namespace, "snapshot.")
isSnapshot := strings.HasPrefix(t.Namespace, "0x")
if isSnapshot { if isSnapshot {
return errors.New("No new claims can be added to a Snapshot") return errors.New("No new claims can be added to a Snapshot")
} }
@ -100,15 +99,16 @@ func (t *Tree) Dump() ([]string, error) {
func (t *Tree) Snapshot() (string, error) { func (t *Tree) Snapshot() (string, error) {
substorage := t.DbStorage.WithPrefix([]byte(t.Namespace)) substorage := t.DbStorage.WithPrefix([]byte(t.Namespace))
nsHash := merkletree.HashBytes([]byte(t.Namespace)) nsHash := merkletree.HashBytes([]byte(t.Namespace))
currentTime := int64(time.Now().Unix())
snapshotNamespace := fmt.Sprintf("snapshot.%s.%d", t.Namespace, currentTime)
snapshotNamespace := t.GetRoot()
fmt.Printf("Snapshoting %s\n", snapshotNamespace)
t.Namespace = snapshotNamespace
substorage.Iterate(func(key, value []byte) { substorage.Iterate(func(key, value []byte) {
nsValue := value[5:37] nsValue := value[5:37]
if fmt.Sprint(nsHash) == fmt.Sprint(nsValue) { if fmt.Sprint(nsHash) == fmt.Sprint(nsValue) {
fmt.Printf("%x\n", value)
data := value[69:] data := value[69:]
//fmt.Printf(" Adding value: %s\n", data)
claim := mkcore.NewGenericClaim(snapshotNamespace, "default", data, nil)
err := t.Tree.Add(claim)
//claim := mkcore.NewGenericClaim(snapshotNamespace, "default", data, nil)
err := t.AddClaim(data)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }

Loading…
Cancel
Save