Browse Source

Keep adapting the code to new merkletree implementation

Use different database storages and merkletree for each censusID

Signed-off-by: p4u <p4u@dabax.net>
feature_chain_module
p4u 5 years ago
parent
commit
dad369ebff
5 changed files with 74 additions and 70 deletions
  1. +6
    -4
      cmd/censushttp/README.md
  2. +15
    -8
      cmd/censushttp/censushttp.go
  3. +0
    -15
      service/README.md
  4. +37
    -37
      service/censusmanager.go
  5. +16
    -6
      tree/tree.go

+ 6
- 4
cmd/censushttp/README.md

@ -13,14 +13,14 @@ go build -o censusHttpService github.com/vocdoni/dvote-census/cmd/censushttp
#### 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
@ -35,6 +35,8 @@ If public key authentication enabled, `signature` field is required using Nancl
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",
"claimData":"Jon Snow",

+ 15
- 8
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 @@ func main() {
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")
}

+ 0
- 15
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)
```

+ 37
- 37
service/censusmanager.go

@ -9,16 +9,14 @@ import (
"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 @@ type Result struct {
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 @@ func checkRequest(w http.ResponseWriter, req *http.Request) bool {
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 @@ func checkAuth(timestamp, signature, message string) bool {
}
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 checkAuth(timestamp, signature, message string) bool {
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 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
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 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
}
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 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
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 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
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 @@ func claimHandler(w http.ResponseWriter, req *http.Request, op string) {
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,
@ -211,13 +218,6 @@ func Listen(port int, proto string, pubKey string) {
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")
if err := srv.ListenAndServeTLS("server.crt", "server.key"); err != nil {

+ 16
- 6
tree/tree.go

@ -12,19 +12,21 @@ import (
)
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 @@ func (t *Tree) GetClaim(data []byte) (*mkcore.ClaimBasic, error) {
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 @@ func (t *Tree) Dump() ([]string, error) {
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

Loading…
Cancel
Save