Keep adapting the code to new merkletree implementation Use different database storages and merkletree for each censusID Signed-off-by: p4u <p4u@dabax.net>
p4u p4u@dabax.net
Fri, 01 Feb 2019 20:20:34 +0100
5 files changed,
74 insertions(+),
70 deletions(-)
M
cmd/censushttp/README.md
→
cmd/censushttp/README.md
@@ -13,14 +13,14 @@ ```
#### Usage -`./censusHttpService <port> [publicKey]` +`./censusHttpService <port> <namespace>[:pubKey] [<namespace>[:pubKey] ...]` Example: ``` -./censusHttpService 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 +./censusHttpService 1500 Got_Favorite +2019/02/01 20:01:15 Starting process HTTP service on port 1500 for namespace GoT_Favorite +2019/02/01 20:01:15 Starting server in http mode ``` #### add claims@@ -34,6 +34,8 @@
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` + +There is a time window of 10 seconds while the signature is considered valid. ``` curl -d '{"censusID":"GoT_Favorite",
M
cmd/censushttp/censushttp.go
→
cmd/censushttp/censushttp.go
@@ -4,13 +4,15 @@ import (
"log" "os" "strconv" + "strings" censusmanager "github.com/vocdoni/dvote-census/service" ) func main() { if len(os.Args) < 2 { - log.Fatal("Usage: " + os.Args[0] + " <port> [pubKey]") + log.Fatal("Usage: " + os.Args[0] + + " <port> <namespace>[:pubKey] [<namespace>[:pubKey]]...") os.Exit(2) } port, err := strconv.Atoi(os.Args[1])@@ -18,13 +20,18 @@ if err != nil {
log.Fatal(err) os.Exit(2) } - pubK := "" - if len(os.Args) > 2 { - log.Print("Public key authentication enabled") - pubK = os.Args[2] + for i := 2; i < len(os.Args); i++ { + s := strings.Split(os.Args[i], ":") + ns := s[0] + pubK := "" + if len(s) > 1 { + pubK = s[1] + log.Printf("Public Key authentication enabled on namespace %s\n", ns) + } + censusmanager.AddNamespace(ns, pubK) + log.Printf("Starting process HTTP service on port %d for namespace %s\n", + port, ns) } - log.Print("Starting process HTTP service on port " + os.Args[1]) - censusmanager.T.Init() - censusmanager.Listen(port, "http", pubK) + censusmanager.Listen(port, "http") }
D
service/README.md
@@ -1,15 +0,0 @@
-## dvot-census http service library - -#### How to use it - -``` -processHttp.T.Init() -processHttp.Listen(1500, "http", "") -``` - -To enable authentication (using pubKey signature): - -``` -pubK := "39f54ce5293520b689f6658ea7f3401f4ff931fa3d90dea21ff901cdf82bb8aa" -processHttp.Listen(1500, "http", pubK) -```
M
service/censusmanager.go
→
service/censusmanager.go
@@ -9,16 +9,14 @@ "strconv"
"strings" "time" - "github.com/vocdoni/dvote-census/tree" - "github.com/vocdoni/dvote-relay/crypto/signature" + tree "github.com/vocdoni/dvote-census/tree" + signature "github.com/vocdoni/dvote-relay/crypto/signature" ) -const authTimeWindow = 10 // Time window (seconds) in which TimeStamp will be accepted if auth enabled - -var authPubKey string - -var T tree.Tree // MerkleTree dvote-census library -var S signature.SignKeys // Signature dvote-relay library +const authTimeWindow = 10 // Time window (seconds) in which TimeStamp will be accepted if auth enabled +var MkTrees map[string]*tree.Tree // MerkleTree dvote-census library +var Signatures map[string]string +var Signature signature.SignKeys // Signature dvote-relay library type Claim struct { CensusID string `json:"censusID"` // References to MerkleTree namespace@@ -33,6 +31,20 @@ Error bool `json:"error"`
Response string `json:"response"` } +func AddNamespace(name, pubKey string) { + if len(MkTrees) == 0 { + MkTrees = make(map[string]*tree.Tree) + } + if len(Signatures) == 0 { + Signatures = make(map[string]string) + } + + mkTree := tree.Tree{} + mkTree.Init(name) + MkTrees[name] = &mkTree + Signatures[name] = pubKey +} + func reply(resp *Result, w http.ResponseWriter) { err := json.NewEncoder(w).Encode(resp) if err != nil {@@ -50,8 +62,8 @@ }
return true } -func checkAuth(timestamp, signature, message string) bool { - if len(authPubKey) < 1 { +func checkAuth(timestamp, signature, pubKey, message string) bool { + if len(pubKey) < 1 { return true } currentTime := int64(time.Now().Unix())@@ -62,7 +74,7 @@ return false
} if timeStampRemote < currentTime+authTimeWindow && timeStampRemote > currentTime-authTimeWindow { - v, err := S.Verify(message, signature, authPubKey) + v, err := Signature.Verify(message, signature, pubKey) if err != nil { log.Printf("Verification error: %s\n", err) }@@ -74,6 +86,7 @@
func claimHandler(w http.ResponseWriter, req *http.Request, op string) { var c Claim var resp Result + if ok := checkRequest(w, req); !ok { return }@@ -89,31 +102,25 @@ 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.Response = "" - + censusFound := false if len(c.CensusID) > 0 { - T.Namespace = c.CensusID - } else { - resp.Error = true - resp.Response = "censusID is not valid" - reply(&resp, w) - return + _, censusFound = MkTrees[c.CensusID] } - - if len(c.ClaimData) < 0 { + if !censusFound { resp.Error = true - resp.Response = "data not valid" + resp.Response = "censusID not valid or not found" reply(&resp, w) return } if op == "add" { 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, Signatures[c.CensusID], msg); auth { 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)) + err = MkTrees[c.CensusID].AddClaim([]byte(c.ClaimData)) } } else { resp.Error = true@@ -122,15 +129,15 @@ }
} if op == "gen" { - resp.Response, err = T.GenProof([]byte(c.ClaimData)) + resp.Response, err = MkTrees[c.CensusID].GenProof([]byte(c.ClaimData)) } if op == "root" { - resp.Response = T.GetRoot() + resp.Response = MkTrees[c.CensusID].GetRoot() } if op == "dump" { - values, err := T.Dump() + values, err := MkTrees[c.CensusID].Dump() if err != nil { resp.Error = true resp.Response = fmt.Sprint(err)@@ -147,12 +154,12 @@ }
if op == "snapshot" { 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, Signatures[c.CensusID], msg); auth { if strings.HasPrefix(c.CensusID, "0x") { resp.Error = true resp.Response = "snapshot an snapshot makes no sense" } else { - snapshotNamespace, err := T.Snapshot() + snapshotNamespace, err := MkTrees[c.CensusID].Snapshot() if err != nil { resp.Error = true resp.Response = fmt.Sprint(err)@@ -171,7 +178,7 @@ if len(c.ProofData) < 1 {
resp.Error = true resp.Response = "proofData not provided" } else { - validProof, _ := T.CheckProof([]byte(c.ClaimData), c.ProofData) + validProof, _ := MkTrees[c.CensusID].CheckProof([]byte(c.ClaimData), c.ProofData) if validProof { resp.Response = "valid" } else {@@ -183,7 +190,7 @@
reply(&resp, w) } -func Listen(port int, proto string, pubKey string) { +func Listen(port int, proto string) { srv := &http.Server{ Addr: fmt.Sprintf(":%d", port), ReadHeaderTimeout: 4 * time.Second,@@ -210,13 +217,6 @@ })
http.HandleFunc("/dump", func(w http.ResponseWriter, r *http.Request) { claimHandler(w, r, "dump") }) - - if len(pubKey) > 1 { - log.Printf("Enabling signature authentication with %s\n", pubKey) - authPubKey = pubKey - } else { - authPubKey = "" - } if proto == "https" { log.Print("Starting server in https mode")
M
tree/tree.go
→
tree/tree.go
@@ -12,19 +12,21 @@ merkletree "github.com/iden3/go-iden3/merkletree"
) type Tree struct { - Namespace string Storage string Tree *merkletree.MerkleTree DbStorage *db.LevelDbStorage } -func (t *Tree) Init() error { +func (t *Tree) Init(namespace string) error { if len(t.Storage) < 1 { + if len(namespace) < 1 { + return errors.New("namespace not valid") + } usr, err := user.Current() if err == nil { - t.Storage = usr.HomeDir + "/.dvote/Tree" + t.Storage = usr.HomeDir + "/.dvote/census/" + namespace } else { - t.Storage = "./dvoteTree" + t.Storage = "./dvoteTree/" + namespace } } mtdb, err := db.NewLevelDbStorage(t.Storage, false)@@ -49,7 +51,7 @@ if len(data) > 496/8 {
return nil, errors.New("claim data too large") } for i := len(data); i <= 496/8; i++ { - data = append(data, byte('0')) + data = append(data, byte('.')) } var indexSlot [400 / 8]byte var dataSlot [496 / 8]byte@@ -106,7 +108,15 @@ var response []string
err := t.Tree.Walk(t.Tree.RootKey(), func(n *merkletree.Node) { if n.Type == merkletree.NodeTypeLeaf { - response = append(response, fmt.Sprintf("|%s", n.Entry.Data)) + rawValue := n.Value() + var cleanValue []byte + for i := 0; i < len(rawValue); i++ { + if rawValue[i] == byte('.') { + break + } + cleanValue = append(cleanValue, rawValue[i]) + } + response = append(response, fmt.Sprintf("%s", cleanValue)) } }) return response, err