diff --git a/service/censusmanager.go b/service/censusmanager.go index 4bb6da1..aad9dc5 100644 --- a/service/censusmanager.go +++ b/service/censusmanager.go @@ -6,13 +6,13 @@ import ( "log" "net/http" "strconv" - "strings" "time" tree "github.com/vocdoni/dvote-census/tree" signature "github.com/vocdoni/dvote-relay/crypto/signature" ) +const hashSize = 32 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 @@ -20,6 +20,7 @@ var Signature signature.SignKeys // Signature dvote-relay library type Claim struct { CensusID string `json:"censusID"` // References to MerkleTree namespace + RootHash string `json:"rootHash"` // References to MerkleTree rootHash ClaimData string `json:"claimData"` // Data to add to the MerkleTree ProofData string `json:"proofData"` // MerkleProof to check TimeStamp string `json:"timeStamp"` // Unix TimeStamp in seconds @@ -98,8 +99,9 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) { } // Process data - log.Printf("Received censusID:{%s} claimData:{%s} proofData:{%s} timeStamp:{%s} signature:{%s}\n", - c.CensusID, c.ClaimData, c.ProofData, c.TimeStamp, c.Signature) + log.Printf("censusID:{%s} rootHash:{%s} claimData:{%s} proofData:{%s} timeStamp:{%s} signature:{%s}\n", + c.CensusID, c.RootHash, c.ClaimData, c.ProofData, c.TimeStamp, c.Signature) + authString := fmt.Sprintf("%s%s%s%s", c.CensusID, c.RootHash, c.ClaimData, c.TimeStamp) resp.Error = false resp.Response = "" censusFound := false @@ -114,14 +116,8 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) { } if op == "add" { - msg := fmt.Sprintf("%s%s%s", c.CensusID, c.ClaimData, c.TimeStamp) - 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 = MkTrees[c.CensusID].AddClaim([]byte(c.ClaimData)) - } + if auth := checkAuth(c.TimeStamp, c.Signature, Signatures[c.CensusID], authString); auth { + err = MkTrees[c.CensusID].AddClaim([]byte(c.ClaimData)) } else { resp.Error = true resp.Response = "invalid authentication" @@ -129,61 +125,107 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) { } if op == "gen" { - resp.Response, err = MkTrees[c.CensusID].GenProof([]byte(c.ClaimData)) + var t *tree.Tree + var err error + if len(c.RootHash) > 1 { //if rootHash specified + t, err = MkTrees[c.CensusID].Snapshot(c.RootHash) + if err != nil { + log.Printf("Snapshot error: %s", err.Error()) + resp.Error = true + resp.Response = "invalid root hash" + reply(&resp, w) + return + } + } else { //if rootHash not specified use current tree + t = MkTrees[c.CensusID] + } + resp.Response, err = t.GenProof([]byte(c.ClaimData)) + if err != nil { + resp.Error = true + resp.Response = err.Error() + reply(&resp, w) + return + } } if op == "root" { resp.Response = MkTrees[c.CensusID].GetRoot() } + if op == "idx" { + + } + if op == "dump" { - values, err := MkTrees[c.CensusID].Dump() + var t *tree.Tree + if auth := checkAuth(c.TimeStamp, c.Signature, Signatures[c.CensusID], authString); !auth { + resp.Error = true + resp.Response = "invalid authentication" + reply(&resp, w) + return + } + + if len(c.RootHash) > 1 { //if rootHash specified + t, err = MkTrees[c.CensusID].Snapshot(c.RootHash) + if err != nil { + log.Printf("Snapshot error: %s", err.Error()) + resp.Error = true + resp.Response = "invalid root hash" + reply(&resp, w) + return + } + } else { //if rootHash not specified use current merkletree + t = MkTrees[c.CensusID] + } + + //dump the claim data and return it + values, err := t.Dump() if err != nil { resp.Error = true - resp.Response = fmt.Sprint(err) + resp.Response = err.Error() } else { jValues, err := json.Marshal(values) if err != nil { resp.Error = true - resp.Response = fmt.Sprint(err) + resp.Response = err.Error() } else { resp.Response = string(jValues) } } } - if op == "snapshot" { - msg := fmt.Sprintf("%s%s%s", c.CensusID, c.ClaimData, c.TimeStamp) - if auth := checkAuth(c.TimeStamp, c.Signature, Signatures[c.CensusID], msg); auth { - if strings.HasPrefix(c.CensusID, "0x") { + if op == "check" { + if len(c.ProofData) < 1 { + resp.Error = true + resp.Response = "proofData not provided" + reply(&resp, w) + return + } + var t *tree.Tree + if len(c.RootHash) > 1 { //if rootHash specified + t, err = MkTrees[c.CensusID].Snapshot(c.RootHash) + if err != nil { + log.Printf("Snapshot error: %s", err.Error()) resp.Error = true - resp.Response = "snapshot an snapshot makes no sense" - } else { - snapshotNamespace, err := MkTrees[c.CensusID].Snapshot() - if err != nil { - resp.Error = true - resp.Response = fmt.Sprint(err) - } else { - resp.Response = snapshotNamespace - } + resp.Response = "invalid root hash" + reply(&resp, w) + return } - } else { - resp.Error = true - resp.Response = "invalid authentication" + } else { //if rootHash not specified use current merkletree + t = MkTrees[c.CensusID] } - } - if op == "check" { - if len(c.ProofData) < 1 { + validProof, err := t.CheckProof([]byte(c.ClaimData), c.ProofData) + if err != nil { resp.Error = true - resp.Response = "proofData not provided" + resp.Response = err.Error() + reply(&resp, w) + return + } + if validProof { + resp.Response = "valid" } else { - validProof, _ := MkTrees[c.CensusID].CheckProof([]byte(c.ClaimData), c.ProofData) - if validProof { - resp.Response = "valid" - } else { - resp.Response = "invalid" - } + resp.Response = "invalid" } } @@ -211,9 +253,6 @@ func Listen(port int, proto string) { http.HandleFunc("/getRoot", func(w http.ResponseWriter, r *http.Request) { claimHandler(w, r, "root") }) - http.HandleFunc("/snapshot", func(w http.ResponseWriter, r *http.Request) { - claimHandler(w, r, "snapshot") - }) http.HandleFunc("/dump", func(w http.ResponseWriter, r *http.Request) { claimHandler(w, r, "dump") }) diff --git a/tree/tree.go b/tree/tree.go index 4ebeac6..d3bf3e3 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -1,8 +1,8 @@ package tree import ( + "bytes" "errors" - "fmt" "os/user" common3 "github.com/iden3/go-iden3/common" @@ -103,6 +103,16 @@ func (t *Tree) GetRoot() string { return t.Tree.RootKey().String() } +func (t *Tree) GetIndex(data []byte) (string, error) { + e, err := t.GetClaim(data) + if err != nil { + return "", err + } + index, err := t.Tree.GetDataByIndex(e.Entry().HIndex()) + return index.String(), err +} + +/* func (t *Tree) Dump() ([]string, error) { var response []string @@ -121,8 +131,20 @@ func (t *Tree) Dump() ([]string, error) { }) return response, err } +*/ + +func (t *Tree) Dump() (string, error) { + w := bytes.NewBufferString("") + err := t.Tree.DumpClaims(w, nil) // as rootKey we can pass a nil pointer, and it will use the current RootKey + + return w.String(), err +} -func (t *Tree) Snapshot() (string, error) { - snapshotNamespace := t.Tree.RootKey().String() - return snapshotNamespace, nil +func (t *Tree) Snapshot(root string) (*Tree, error) { + var rootHash merkletree.Hash + copy(rootHash[:32], root) + mt, err := t.Tree.Snapshot(&rootHash) + snapshotTree := new(Tree) + snapshotTree.Tree = mt + return snapshotTree, err }