Skip to content

Commit

Permalink
Merge pull request #3 from rarimo/fix/validate-credentials-params
Browse files Browse the repository at this point in the history
Update: proof validation with additional configurable info
  • Loading branch information
mhrynenko authored May 23, 2024
2 parents cef6dbe + 13399ec commit b86d475
Show file tree
Hide file tree
Showing 14 changed files with 268 additions and 60 deletions.
5 changes: 5 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ verifier:
verification_key_path: "./verification_key.json"
allowed_age: 18
allowed_citizenships: ["UKR"]
allowed_event_id: "event_id"
allowed_query_selector: "query_selector"
# at least one of these should be correct to pass:
allowed_identity_count: 1
allowed_identity_timestamp: 1715698750

root_verifier:
rpc: evm_rpc_url
Expand Down
26 changes: 26 additions & 0 deletions docs/spec/components/schemas/AirdropParams.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
allOf:
- $ref: '#/components/schemas/AirdropKey'
- type: object
required:
- attributes
properties:
attributes:
type: object
required:
- event_id
- query_selector
- started_at
properties:
event_id:
type: string
description: Event identifier that is generated during ZKP query creation
example: "304351862882731539112827930982999985591702317710421481944329166111111129570"
started_at:
type: integer
format: int64
description: Unix timestamp in seconds when airdrop event starts
example: 1716381206
query_selector:
type: string
description: Query selector that is used for proof generation
example: 123
17 changes: 17 additions & 0 deletions docs/spec/paths/integrations@airdrop-svc@[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
get:
tags:
- Airdrop
summary: Get airdrop event parameters
description: Get an airdrop parameters for integration.
operationId: GetAirdropParams
responses:
200:
content:
application/vnd.api+json:
schema:
type: object
required:
- data
properties:
data:
$ref: '#/components/schemas/AirdropParams'
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/iden3/go-rapidsnark/types v0.0.3
github.com/rarimo/rarimo-core v0.0.0-20231004143803-6b209428ecbf
github.com/rarimo/zkverifier-kit v0.2.0
github.com/rarimo/zkverifier-kit v0.2.1
github.com/rubenv/sql-migrate v1.6.1
gitlab.com/distributed_lab/ape v1.7.1
gitlab.com/distributed_lab/figure/v3 v3.1.4
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2106,8 +2106,12 @@ github.com/rarimo/cosmos-sdk v0.46.7 h1:jU2PiWzc+19SF02cXM0O0puKPeH1C6Q6t2lzJ9s1
github.com/rarimo/cosmos-sdk v0.46.7/go.mod h1:fqKqz39U5IlEFb4nbQ72951myztsDzFKKDtffYJ63nk=
github.com/rarimo/rarimo-core v0.0.0-20231004143803-6b209428ecbf h1:NvYhOErW0d7ohn2YzGxQYKssrgVrKOvjrKL1OBQgCB4=
github.com/rarimo/rarimo-core v0.0.0-20231004143803-6b209428ecbf/go.mod h1:Onkd0EJP94hw4dT/2KH7QXRwDG4eIGeaMffSjA1i6/s=
github.com/rarimo/zkverifier-kit v0.2.0 h1:FybrsDdpP/x/m0ZtEeU9lcHsztlPtCBLo67unAdbFGA=
github.com/rarimo/zkverifier-kit v0.2.0/go.mod h1:ROaCxusG9WLNwbqlTBKqZCm8tQrNdnwLyRWtS+yxO8o=
github.com/rarimo/zkverifier-kit v0.2.1-rc.4 h1:ZpCY2toKFroHK6lpttrkZ0wvb27JbZU5L15N8KSfblc=
github.com/rarimo/zkverifier-kit v0.2.1-rc.4/go.mod h1:3YDg5dTkDRr4IdfaDHGYetopd6gS/2SuwSeseYTWwNw=
github.com/rarimo/zkverifier-kit v0.2.1-rc.5 h1:NN7iW40q3p6EIfAd7bxF0XdisV8AyrMQJ3g28FUstZw=
github.com/rarimo/zkverifier-kit v0.2.1-rc.5/go.mod h1:3YDg5dTkDRr4IdfaDHGYetopd6gS/2SuwSeseYTWwNw=
github.com/rarimo/zkverifier-kit v0.2.1 h1:t/5L27RIKQEtXmocPcNeta3XV5oxz891g8NFCLeIsao=
github.com/rarimo/zkverifier-kit v0.2.1/go.mod h1:3YDg5dTkDRr4IdfaDHGYetopd6gS/2SuwSeseYTWwNw=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg=
Expand Down
19 changes: 9 additions & 10 deletions internal/config/broadcaster.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package config

import (
"crypto/tls"
"fmt"
"time"

Expand All @@ -21,7 +20,7 @@ import (
"gitlab.com/distributed_lab/kit/comfig"
"gitlab.com/distributed_lab/kit/kv"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
)

Expand Down Expand Up @@ -73,14 +72,14 @@ func (b *broadcasterer) Broadcaster() Broadcaster {
panic(fmt.Errorf("broadcaster: invalid airdrop amount: %w", err))
}

// this hack is required to dial gRPC, please test it with remote RPC if you change this code
withInsecure := grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true,
}))
cosmosRPC, err := grpc.Dial(cfg.CosmosRPC, withInsecure, grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: 10 * time.Second, // wait time before ping if no activity
Timeout: 20 * time.Second, // ping timeout
}))
cosmosRPC, err := grpc.Dial(
cfg.CosmosRPC,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: 10 * time.Second, // wait time before ping if no activity
Timeout: 20 * time.Second, // ping timeout
}),
)
if err != nil {
panic(fmt.Errorf("broadcaster: failed to dial cosmos core rpc: %w", err))
}
Expand Down
41 changes: 32 additions & 9 deletions internal/config/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,27 @@ import (
"gitlab.com/distributed_lab/kit/kv"
)

const proofEventIDValue = "304358862882731539112827930982999386691702727710421481944329166126417129570"
type GlobalParams struct {
EventID string
QuerySelector string
AirdropStart int64
}

type Verifierer struct {
Params GlobalParams
ZkVerifier *zk.Verifier
}

func (c *Config) Verifier() *zk.Verifier {
func (c *Config) Verifier() *Verifierer {
return c.verifier.Do(func() interface{} {
var cfg struct {
VerificationKeyPath string `fig:"verification_key_path,required"`
AllowedAge int `fig:"allowed_age,required"`
AllowedCitizenships []string `fig:"allowed_citizenships,required"`
VerificationKeyPath string `fig:"verification_key_path,required"`
AllowedAge int `fig:"allowed_age,required"`
AllowedCitizenships []string `fig:"allowed_citizenships,required"`
AllowedQuerySelector string `fig:"allowed_query_selector,required"`
AllowedEventID string `fig:"allowed_event_id,required"`
AllowedIdentityCount int64 `fig:"allowed_identity_count,required"`
AllowedIdentityTimestamp int64 `fig:"allowed_identity_timestamp,required"`
}

err := figure.
Expand All @@ -31,14 +44,24 @@ func (c *Config) Verifier() *zk.Verifier {
zk.WithVerificationKeyFile(cfg.VerificationKeyPath),
zk.WithCitizenships(cfg.AllowedCitizenships...),
zk.WithAgeAbove(cfg.AllowedAge),
zk.WithEventID(proofEventIDValue),
zk.WithRootVerifier(c.ProvideVerifier()),
zk.WithProofSelectorValue(cfg.AllowedQuerySelector),
zk.WithEventID(cfg.AllowedEventID),
zk.WithIdentityVerifier(c.ProvideVerifier()),
zk.WithIdentitiesCounter(cfg.AllowedIdentityCount),
zk.WithIdentitiesCreationTimestampLimit(cfg.AllowedIdentityTimestamp),
)

if err != nil {
panic(fmt.Errorf("failed to initialize passport verifier: %w", err))
}

return v
}).(*zk.Verifier)
return &Verifierer{
ZkVerifier: v,
Params: GlobalParams{
AirdropStart: cfg.AllowedIdentityTimestamp,
EventID: cfg.AllowedEventID,
QuerySelector: cfg.AllowedQuerySelector,
},
}
}).(*Verifierer)
}
4 changes: 2 additions & 2 deletions internal/service/handlers/create_airdrop.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) {
return
}

nullifier := req.Data.Attributes.ZkProof.PubSignals[zk.PubSignalNullifier]
nullifier := req.Data.Attributes.ZkProof.PubSignals[zk.Nullifier]

airdrop, err := AirdropsQ(r).
FilterByNullifier(nullifier).
Expand All @@ -38,7 +38,7 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) {
return
}

err = Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithAddress(req.Data.Attributes.Address))
err = Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithRarimoAddress(req.Data.Attributes.Address))
if err != nil {
if errors.Is(err, identity.ErrContractCall) {
Log(r).WithError(err).Error("Failed to verify proof")
Expand Down
12 changes: 12 additions & 0 deletions internal/service/handlers/ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"net/http"

"github.com/rarimo/airdrop-svc/internal/config"
"github.com/rarimo/airdrop-svc/internal/data"
zk "github.com/rarimo/zkverifier-kit"
"gitlab.com/distributed_lab/logan/v3"
Expand All @@ -16,6 +17,7 @@ const (
airdropsQCtxKey
airdropAmountCtxKey
verifierCtxKey
airdropParamsCtxKey
)

func CtxLog(entry *logan.Entry) func(context.Context) context.Context {
Expand Down Expand Up @@ -48,6 +50,16 @@ func AirdropAmount(r *http.Request) string {
return r.Context().Value(airdropAmountCtxKey).(string)
}

func CtxAirdropParams(amount config.GlobalParams) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, airdropParamsCtxKey, amount)
}
}

func AirdropParams(r *http.Request) config.GlobalParams {
return r.Context().Value(airdropParamsCtxKey).(config.GlobalParams)
}

func CtxVerifier(entry *zk.Verifier) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, verifierCtxKey, entry)
Expand Down
23 changes: 23 additions & 0 deletions internal/service/handlers/get_airdrop_params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package handlers

import (
"net/http"

"github.com/rarimo/airdrop-svc/resources"
"gitlab.com/distributed_lab/ape"
)

func GetAirdropParams(w http.ResponseWriter, r *http.Request) {
ape.Render(w, resources.AirdropParamsResponse{
Data: resources.AirdropParams{
Key: resources.Key{
Type: resources.AIRDROP,
},
Attributes: resources.AirdropParamsAttributes{
EventId: AirdropParams(r).EventID,
StartedAt: AirdropParams(r).AirdropStart,
QuerySelector: AirdropParams(r).QuerySelector,
},
},
})
}
4 changes: 3 additions & 1 deletion internal/service/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ func Run(ctx context.Context, cfg *config.Config) {
ape.LoganMiddleware(cfg.Log()),
ape.CtxMiddleware(
handlers.CtxLog(cfg.Log()),
handlers.CtxVerifier(cfg.Verifier()),
handlers.CtxVerifier(cfg.Verifier().ZkVerifier),
handlers.CtxAirdropAmount(cfg.Broadcaster().AirdropCoins.String()),
handlers.CtxAirdropParams(cfg.Verifier().Params),
),
handlers.DBCloneMiddleware(cfg.DB()),
)
r.Route("/integrations/airdrop-svc/airdrops", func(r chi.Router) {
r.Post("/", handlers.CreateAirdrop)
r.Get("/{nullifier}", handlers.GetAirdrop)
r.Get("/params", handlers.GetAirdropParams)
})

cfg.Log().Info("Service started")
Expand Down
43 changes: 43 additions & 0 deletions resources/model_airdrop_params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* GENERATED. Do not modify. Your changes might be overwritten!
*/

package resources

import "encoding/json"

type AirdropParams struct {
Key
Attributes AirdropParamsAttributes `json:"attributes"`
}
type AirdropParamsResponse struct {
Data AirdropParams `json:"data"`
Included Included `json:"included"`
}

type AirdropParamsListResponse struct {
Data []AirdropParams `json:"data"`
Included Included `json:"included"`
Links *Links `json:"links"`
Meta json.RawMessage `json:"meta,omitempty"`
}

func (r *AirdropParamsListResponse) PutMeta(v interface{}) (err error) {
r.Meta, err = json.Marshal(v)
return err
}

func (r *AirdropParamsListResponse) GetMeta(out interface{}) error {
return json.Unmarshal(r.Meta, out)
}

// MustAirdropParams - returns AirdropParams from include collection.
// if entry with specified key does not exist - returns nil
// if entry with specified key exists but type or ID mismatches - panics
func (c *Included) MustAirdropParams(key Key) *AirdropParams {
var airdropParams AirdropParams
if c.tryFindEntry(key, &airdropParams) {
return &airdropParams
}
return nil
}
14 changes: 14 additions & 0 deletions resources/model_airdrop_params_attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* GENERATED. Do not modify. Your changes might be overwritten!
*/

package resources

type AirdropParamsAttributes struct {
// Event identifier that is generated during ZKP query creation
EventId string `json:"event_id"`
// Query selector that is used for proof generation
QuerySelector string `json:"query_selector"`
// Unix timestamp in seconds when airdrop event starts
StartedAt int64 `json:"started_at"`
}
Loading

0 comments on commit b86d475

Please sign in to comment.