mirror of
https://github.com/arnaucube/go-dvote.git
synced 2026-02-28 05:26:46 +01:00
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>
This commit is contained in:
@@ -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 get -u github.com/vocdoni/dvote-census
|
||||||
go build -o httpService http_census_service.go
|
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"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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\"]"}
|
|
||||||
```
|
|
||||||
@@ -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,
|
log.Printf("Received censusID:{%s} claimData:{%s} proofData:{%s} timeStamp:{%s} signature:{%s}\n",
|
||||||
c.TimeStamp, c.Signature)
|
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 strings.HasPrefix(c.CensusID, "0x") {
|
||||||
if err != nil {
|
|
||||||
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
|
||||||
|
|||||||
14
tree/tree.go
14
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 := t.GetRoot()
|
||||||
snapshotNamespace := fmt.Sprintf("snapshot.%s.%d", t.Namespace, currentTime)
|
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)
|
||||||
claim := mkcore.NewGenericClaim(snapshotNamespace, "default", data, nil)
|
err := t.AddClaim(data)
|
||||||
err := t.Tree.Add(claim)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user