Browse Source

Add snapshot and dump methods

Signed-off-by: p4u <p4u@dabax.net>
feature_chain_module
p4u 5 years ago
parent
commit
4f72b43600
4 changed files with 156 additions and 38 deletions
  1. +29
    -0
      service/README.md
  2. +38
    -1
      service/processHttp.go
  3. +1
    -1
      tree/README.md
  4. +88
    -36
      tree/tree.go

+ 29
- 0
service/README.md

@ -19,6 +19,7 @@ processHttp.Listen(1500, "http", pubK)
``` ```
curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/addClaim curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:1500/addClaim
{"error":false,"response":""} {"error":false,"response":""}
``` ```
@ -27,6 +28,7 @@ curl -d '{"censusID":"GoT_Favorite",
"claimData":"Jon Snow", "claimData":"Jon Snow",
"timeStamp":"1547814675", "timeStamp":"1547814675",
"signature":"a117c4ce12b29090884112ffe57e664f007e7ef142a1679996e2d34fd2b852fe76966e47932f1e9d3a54610d0f361383afe2d9aab096e15d136c236abb0a0d0e"}' http://localhost:1500/addClaim "signature":"a117c4ce12b29090884112ffe57e664f007e7ef142a1679996e2d34fd2b852fe76966e47932f1e9d3a54610d0f361383afe2d9aab096e15d136c236abb0a0d0e"}' http://localhost:1500/addClaim
{"error":false,"response":""} {"error":false,"response":""}
``` ```
@ -34,6 +36,7 @@ The signature message is a concatenation of the following strings: `censusID, cl
``` ```
curl -d '{"censusID":"GoT_Favorite","claimData":"Tyrion"}' http://localhost:1500/addClaim curl -d '{"censusID":"GoT_Favorite","claimData":"Tyrion"}' http://localhost:1500/addClaim
{"error":false,"response":""} {"error":false,"response":""}
``` ```
@ -41,6 +44,7 @@ curl -d '{"censusID":"GoT_Favorite","claimData":"Tyrion"}' http://localhost:1500
``` ```
curl -d '{"censusID":"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"}
``` ```
@ -48,10 +52,35 @@ curl -d '{"censusID":"GoT_Favorite","claimData":"Jon Snow"}' http://localhost:15
``` ```
curl -d '{"censusID":"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 '{"censusID":"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"}
``` ```
#### 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\"]"}
```

+ 38
- 1
service/processHttp.go

@ -107,7 +107,6 @@ 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)
log.Printf("Msg to check: %s", msg)
if auth := checkAuth(c.TimeStamp, c.Signature, msg); auth { if auth := checkAuth(c.TimeStamp, c.Signature, msg); auth {
err = T.AddClaim([]byte(c.ClaimData)) err = T.AddClaim([]byte(c.ClaimData))
} else { } else {
@ -124,6 +123,38 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
resp.Response = T.GetRoot() resp.Response = T.GetRoot()
} }
if op == "dump" {
values, err := T.Dump()
if err != nil {
resp.Error = true
resp.Response = fmt.Sprint(err)
} else {
jValues, err := json.Marshal(values)
if err != nil {
resp.Error = true
resp.Response = fmt.Sprint(err)
} 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, msg); auth {
snapshotNamespace, err := T.Snapshot()
if err != nil {
resp.Error = true
resp.Response = fmt.Sprint(err)
} else {
resp.Response = snapshotNamespace
}
} else {
resp.Error = true
resp.Response = "invalid authentication"
}
}
if op == "check" { if op == "check" {
if len(c.ProofData) < 1 { if len(c.ProofData) < 1 {
resp.Error = true resp.Error = true
@ -172,6 +203,12 @@ func Listen(port int, proto string, pubKey string) {
http.HandleFunc("/getRoot", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/getRoot", func(w http.ResponseWriter, r *http.Request) {
claimHandler(w, r, "root") 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")
})
if len(pubKey) > 1 { if len(pubKey) > 1 {
log.Printf("Enabling signature authentication with %s\n", pubKey) log.Printf("Enabling signature authentication with %s\n", pubKey)

+ 1
- 1
tree/README.md

@ -19,4 +19,4 @@ Example of usage:
#### To-Do #### To-Do
+ Add export/import methods
Avoid duplicates on dump/snapshot

+ 88
- 36
tree/tree.go

@ -1,36 +1,45 @@
package tree package tree
import ( import (
"github.com/vocdoni/go-iden3/db"
"github.com/vocdoni/go-iden3/merkletree"
mkcore "github.com/vocdoni/go-iden3/core"
common3 "github.com/vocdoni/go-iden3/common"
"os/user"
"errors"
"fmt"
"os/user"
"strings"
"time"
common3 "github.com/vocdoni/go-iden3/common"
mkcore "github.com/vocdoni/go-iden3/core"
"github.com/vocdoni/go-iden3/db"
"github.com/vocdoni/go-iden3/merkletree"
) )
type Tree struct { type Tree struct {
Namespace string
Storage string
Tree *merkletree.MerkleTree
Namespace string
Storage string
Tree *merkletree.MerkleTree
DbStorage *db.LevelDbStorage
} }
func (t *Tree) Init() error { func (t *Tree) Init() error {
if len(t.Storage) < 1 {
usr, err := user.Current()
if err == nil {
t.Storage = usr.HomeDir + "/.dvote/Tree"
} else { t.Storage = "./dvoteTree" }
}
mtdb, err := db.NewLevelDbStorage(t.Storage, false)
if len(t.Storage) < 1 {
usr, err := user.Current()
if err == nil {
t.Storage = usr.HomeDir + "/.dvote/Tree"
} else {
t.Storage = "./dvoteTree"
}
}
mtdb, err := db.NewLevelDbStorage(t.Storage, false)
if err != nil { if err != nil {
return err
return err
} }
mt, err := merkletree.New(mtdb, 140) mt, err := merkletree.New(mtdb, 140)
if err != nil { if err != nil {
return err
return err
} }
t.Tree = mt
return nil
t.DbStorage = mtdb
t.Tree = mt
return nil
} }
func (t *Tree) Close() { func (t *Tree) Close() {
@ -38,29 +47,72 @@ func (t *Tree) Close() {
} }
func (t *Tree) AddClaim(data []byte) error { func (t *Tree) AddClaim(data []byte) error {
claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
return t.Tree.Add(claim)
isSnapshot := strings.Contains(t.Namespace, "snapshot.")
if isSnapshot {
return errors.New("No new claims can be added to a Snapshot")
}
claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
return t.Tree.Add(claim)
} }
func (t *Tree) GenProof(data []byte) (string, error) { func (t *Tree) GenProof(data []byte) (string, error) {
claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
mp, err := t.Tree.GenerateProof(claim.Hi())
if err!=nil {
return "", err
}
mpHex := common3.BytesToHex(mp)
return mpHex, nil
claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
mp, err := t.Tree.GenerateProof(claim.Hi())
if err != nil {
return "", err
}
mpHex := common3.BytesToHex(mp)
return mpHex, nil
} }
func (t *Tree) CheckProof(data []byte, mpHex string) (bool, error) { func (t *Tree) CheckProof(data []byte, mpHex string) (bool, error) {
mp, err := common3.HexToBytes(mpHex)
if err != nil {
return false, err
}
claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
return merkletree.CheckProof(t.Tree.Root(), mp, claim.Hi(), claim.Ht(), t.Tree.NumLevels()), nil
mp, err := common3.HexToBytes(mpHex)
if err != nil {
return false, err
}
claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
return merkletree.CheckProof(t.Tree.Root(), mp, claim.Hi(), claim.Ht(), t.Tree.NumLevels()), nil
}
func (t *Tree) GetRoot() string {
return t.Tree.Root().Hex()
}
/* Dump, Export and Snapshot functions are a bit tricky.
Since go-iden3 does not provide the necessary tools. Low level operations must be performed.
Once go-iden3 API is mature enough, these functions must be adapted.
To explore: Values are stored twice in the BD?
*/
func (t *Tree) Dump() ([]string, error) {
var response []string
substorage := t.DbStorage.WithPrefix([]byte(t.Namespace))
nsHash := merkletree.HashBytes([]byte(t.Namespace))
substorage.Iterate(func(key, value []byte) {
nsValue := value[5:37]
if fmt.Sprint(nsHash) == fmt.Sprint(nsValue) {
response = append(response, string(value[69:]))
}
})
return response, nil
} }
func (t *Tree) GetRoot() (string) {
return t.Tree.Root().Hex()
func (t *Tree) Snapshot() (string, error) {
substorage := t.DbStorage.WithPrefix([]byte(t.Namespace))
nsHash := merkletree.HashBytes([]byte(t.Namespace))
currentTime := int64(time.Now().Unix())
snapshotNamespace := fmt.Sprintf("snapshot.%s.%d", t.Namespace, currentTime)
substorage.Iterate(func(key, value []byte) {
nsValue := value[5:37]
if fmt.Sprint(nsHash) == fmt.Sprint(nsValue) {
data := value[69:]
//fmt.Printf(" Adding value: %s\n", data)
claim := mkcore.NewGenericClaim(snapshotNamespace, "default", data, nil)
err := t.Tree.Add(claim)
if err != nil {
fmt.Println(err)
}
}
})
return snapshotNamespace, nil
} }

Loading…
Cancel
Save