diff --git a/README.md b/README.md index 8dfc097..607e6a5 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Introduction This repository is an SDK for connecting external services with Rarimo passport -verification system that may be used in back-end services. Its main purpose is +verification and voting systems that may be used in back-end services. Its main purpose is providing a convenient methods that can be used in any system without deep introduction in the Rarimo system structure. @@ -20,16 +20,16 @@ import ( ) func main() { - rv := root.NewVerifier(contractCaller, reqTimeout) + passportVerifier := root.NewPoseidonSMTVerifier(rpcURL, contractAddress, reqTimeout) v, err := kit.NewVerifier( - kit.PassportVerification, nil, + kit.WithProofType(kit.GeneralPassport), kit.WithVerificationKeyFile("key.json"), kit.WithEventID("304358862882731539112827930982999386691702727710421481944329166126417129570"), kit.WithAgeAbove(18), kit.WithCitizenships("UKR"), - kit.WithIdentityVerifier(rv), + kit.WithPassportRootVerifier(passportVerifier), kit.WithIdentitiesCounter(0), kit.WithIdentitiesCreationTimestampLimit(1847321000), ) @@ -44,20 +44,55 @@ func main() { } ``` +```go +package main + +import ( + kit "github.com/rarimo/zkverifier-kit" + "github.com/rarimo/zkverifier-kit/root" +) + +func main() { + pollVerifier := root.NewProposalSMTVerifier(rpcURL, reqTimeout) + + v, err := kit.NewVerifier( + nil, + kit.WithProofType(kit.PollParticipation), + kit.WithVerificationKeyFile("key.json"), + kit.WithEventID("304358862882731539112827930982999386691702727710421481944329166126417129570"), + ) + if err != nil { + // ... + } + // data is an abstract event data that you expect to be in proof + err = v.VerifyProof(proof, + kit.WithPollParticipationEventID(pollEventID) , + kit.WithPollRootVerifier(v.WithContract(pollContract))) + if err != nil { + // ... + } +} +``` Let's break this down. ### Configurable root verifier Firstly, you instantiate identity root verifier, which will verify the `IdStateRoot` public signal with contract call. You can refer to our -generated contract bindings in [poseidonsmt](internal/poseidonsmt) package. +generated contract bindings in [poseidonsmt](internal/poseidonsmt) and [proposalsmt](internal/proposalsmt) package. However, maybe, you would like to create the verifier from config map. Here is configuration sample that you should have in `config.yaml` of your app: ```yaml -root_verifier: - rpc: https://your-rpc - contract: 0x... +verifier: + allowed_age: 18 + allowed_identity_timestamp: 1715698750 +poseidonsmt_root_verifier: + rpc: evm_rpc_url + contract: poseidon_smt_contract_address + request_timeout: 10s +proposalsmt_root_verifier: + rpc: evm_rpc_url request_timeout: 10s ``` diff --git a/options.go b/options.go index 1b80fd0..dbc5492 100644 --- a/options.go +++ b/options.go @@ -39,6 +39,9 @@ type VerifyOptions struct { partEventID string // voteVerifier - verifies root in PollParticipation proof type voteVerifier root.Verifier + // skipExpirationCheck - specifies whether to check the expiration date. + // Used for tests only + skipExpirationCheck bool } // VerifyOption type alias for function that may add new values to VerifyOptions structure. @@ -166,6 +169,12 @@ func WithPollRootVerifier(v root.Verifier) VerifyOption { } } +func withSkipExpirationCheck(check bool) VerifyOption { + return func(opts *VerifyOptions) { + opts.skipExpirationCheck = check + } +} + // mergeOptions collects all parameters together and fills VerifyOptions struct // with it, overwriting existing values func mergeOptions(withDefaults bool, opts VerifyOptions, options ...VerifyOption) VerifyOptions { diff --git a/passport.go b/passport.go index 74207c4..e27fce2 100644 --- a/passport.go +++ b/passport.go @@ -113,7 +113,7 @@ func (v *Verifier) validatePubSignals(zkProof zkptypes.ZKProof) error { func (v *Verifier) validatePassportSignals(signals PubSignalGetter) error { err := v.opts.passportVerifier.VerifyRoot(signals.Get(IdStateRoot)) - if !errors.Is(err, root.ErrInvalidRoot) { + if err != nil && !errors.Is(err, root.ErrInvalidRoot) { return err } @@ -145,7 +145,9 @@ func (v *Verifier) validatePassportSignals(signals PubSignalGetter) error { } maps.Copy(all, v.validateBirthDate(signals)) - maps.Copy(all, v.validatePassportExpiration(signals)) + if !v.opts.skipExpirationCheck { + maps.Copy(all, v.validatePassportExpiration(signals)) + } maps.Copy(all, v.validateIdentitiesInputs(signals)) return all.Filter() diff --git a/passport_test.go b/passport_test.go index 2069e41..7a279a7 100644 --- a/passport_test.go +++ b/passport_test.go @@ -25,7 +25,7 @@ const ( usaCitizenship = "USA" engCitizenship = "ENG" - validEventID = "304358862882731539112827930982999386691702727710421481944329166126417129570" + validEventID = "211985299740800702300256033401632392934377086534111448880928528431996790315" invalidEventID = "AC42D1A986804618C7A793FBE814D9B31E47BE51E082806363DCA6958F3062" storedRoot = "1fd232b83b1927f2a8ede62ffe15c31d18782dd513e08f4aabeaf2e8e4c32417" @@ -37,20 +37,18 @@ const verificationKeyFile = "example_verification_key.json" var validProof = zkptypes.ZKProof{ Proof: &zkptypes.ProofData{ - Protocol: "groth16", - A: []string{ - "10580782106790373477261932143775321905443589586433651561536061428214589672484", - "11698250021575150794852451179623994478616360899564591934730721390019157908788", + A: []string{"12996016572939291630814335127078241511084725921569267221560959870881226842779", + "761491852560139542885770222513604531448776143684161133298463831447152162597", "1", }, B: [][]string{ { - "21705525629420011147308188725178223733293601519891005372105977395761857543648", - "21430490393915822750736844419186297691953172223086304113869075235715014505478", + "7599497178424536454186364289381353824249712189259655444764200186031301149772", + "758126175915585817034687017843086369456608327321178876731878325331363448399", }, { - "3610890604725359549886067582256338844864753769852189853964284902205861040749", - "7808595281025880671232006108041019334015054900817419103023248582576073762625", + "6552077155141497820322593297915265785002325660175270629851305329247857575000", + "9398527224370554058809232921797193562676853236790343293937085614424613225502", }, { "1", @@ -58,13 +56,14 @@ var validProof = zkptypes.ZKProof{ }, }, C: []string{ - "14487193913320584434009947494902473354673034787917761246001827312658064548420", - "13206968032646449669115920135803893331131897495922885759651807223610673459946", + "5520540944773640715610133783195440292316265697892695003821987613285146498487", + "18240929522954357307751256221496990071805852196144718742156278323268552814849", "1", }, + Protocol: "groth16", }, PubSignals: []string{ - "7639957125598480790492529006924434106731566948760118579546114507674255247458", + "8558624556173674225153579865966359056844751077624402517288712777973816271870", "0", "0", "0", @@ -73,26 +72,26 @@ var validProof = zkptypes.ZKProof{ "5589842", "0", "0", - "304358862882731539112827930982999386691702727710421481944329166126417129570", - "11318436481061661812577344400351359194387994145300108534310140806143276292370", - "14393086243856018838405247242117964464658357003864077561407424514652280923159", + "211985299740800702300256033401632392934377086534111448880928528431996790315", + "1388928733714245704395968367156897439973029902189556257928944264186457955333", + "16055556473534063237266173531819244891235292810222332599565643356062398286614", "23073", "0", - "1713436478", + "1719823039", "0", - "1", + "3", + "52983525027888", + "53009295290417", + "55199728611377", "52983525027888", - "53009295159860", - "55199728480820", "52983525027888", - "0", }, } // converted from EventData field in validProof.PubSignals var ( - validEventData = []byte{25, 6, 2, 14, 30, 0, 10, 9, 4, 11, 4, 3, 28, 3, 22, 1, 20, 16, 30, 11, 27, 30, 25, 22, 30, 10, 15, 14, 25, 5, 25, 18} - invalidEventData = []byte{174} + validEventData = []byte{3, 18, 27, 22, 5, 4, 24, 11, 14, 27, 18, 30, 20, 25, 23, 16, 5, 12, 16, 16, 26, 31, 20, 1, 28, 21, 20, 10, 13, 19, 28, 5} + invalidEventData = []byte{4, 18, 27, 22, 5, 4, 24, 11, 14, 27, 18, 30, 20, 25, 23, 16, 5, 12, 16, 16, 26, 31, 20, 1, 28, 21, 20, 10, 13, 19, 28, 5} ) var verificationKey []byte @@ -200,7 +199,7 @@ func TestVerifyProof(t *testing.T) { WithProofSelectorValue("23073"), WithEventData(invalidEventData), }, - want: "pub_signals/event_data: must be a valid value", + want: "pub_signals/event_data: event data does not match.", }, { name: "Lower age", @@ -215,6 +214,7 @@ func TestVerifyProof(t *testing.T) { want: "pub_signals/birth_date_upper_bound: dates are not equal", }, { + // We need new proof for every day for pass this test name: "Equal age", initOpts: []VerifyOption{ WithVerificationKeyFile(verificationKeyFile), @@ -314,6 +314,7 @@ func TestVerifyProof(t *testing.T) { want: "", }, { + // We need new proof for every day for pass this test, because of birthdat validation name: "All valid options", initOpts: []VerifyOption{ WithProofType(GlobalPassport), @@ -328,6 +329,8 @@ func TestVerifyProof(t *testing.T) { }, want: "", }, + // TODO: disabled verifier don't return error + // We need provide contract and rpc for bad verifier { name: "Invalid identity verifier", initOpts: []VerifyOption{ @@ -358,6 +361,7 @@ func TestVerifyProof(t *testing.T) { key = verificationKey } + tc.initOpts = append(tc.initOpts, withSkipExpirationCheck(true)) verifier, err := NewVerifier(tc.key, tc.initOpts...) if err != nil { t.Fatal(err)