Skip to content

Commit 9f7320f

Browse files
add auth v3 (#92)
* add auth v3
1 parent 6ed2dc5 commit 9f7320f

File tree

7 files changed

+354
-6
lines changed

7 files changed

+354
-6
lines changed

auth.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ type AuthInputs struct {
2424
Challenge *big.Int
2525
}
2626

27-
// authCircuitInputs type reflect auth.circom private inputs required by prover
28-
type authCircuitInputs struct {
27+
// authV1CircuitInputs type reflect auth.circom private inputs required by prover
28+
type authV1CircuitInputs struct {
2929
UserAuthClaim *core.Claim `json:"userAuthClaim"`
3030
UserAuthClaimMtp []string `json:"userAuthClaimMtp"`
3131
UserAuthClaimNonRevMtp []string `json:"userAuthClaimNonRevMtp"`
@@ -58,7 +58,7 @@ func (a AuthInputs) InputsMarshal() ([]byte, error) {
5858
return nil, errors.New(ErrorEmptyChallengeSignature)
5959
}
6060

61-
s := authCircuitInputs{
61+
s := authV1CircuitInputs{
6262
UserAuthClaim: a.AuthClaim.Claim,
6363
UserAuthClaimMtp: PrepareSiblingsStr(a.AuthClaim.IncProof.Proof.AllSiblings(),
6464
a.GetMTLevel()),

authV2.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type AuthV2Inputs struct {
3131
}
3232

3333
// authCircuitInputs type reflect auth.circom private inputs required by prover
34-
type authV2CircuitInputs struct {
34+
type authCircuitInputs struct {
3535
// ID
3636
GenesisID string `json:"genesisID"`
3737
ProfileNonce string `json:"profileNonce"`
@@ -101,7 +101,7 @@ func (a AuthV2Inputs) InputsMarshal() ([]byte, error) {
101101
return nil, err
102102
}
103103

104-
s := authV2CircuitInputs{
104+
s := authCircuitInputs{
105105
GenesisID: a.GenesisID.BigInt().String(),
106106
ProfileNonce: a.ProfileNonce.String(),
107107
AuthClaim: a.AuthClaim,
@@ -158,7 +158,6 @@ func (a AuthV2Inputs) GetPublicStatesInfo() (StatesInfo, error) {
158158
}, nil
159159
}
160160

161-
162161
// AuthV2PubSignals auth.circom public signals
163162
type AuthV2PubSignals struct {
164163
UserID *core.ID `json:"userID"`

authV3.go

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package circuits
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"math/big"
7+
8+
core "github.com/iden3/go-iden3-core/v2"
9+
"github.com/iden3/go-iden3-crypto/babyjub"
10+
"github.com/iden3/go-merkletree-sql/v2"
11+
"github.com/pkg/errors"
12+
)
13+
14+
// AuthV3Inputs type represent authV3.circom/authV3-8-32.circom inputs
15+
type AuthV3Inputs struct {
16+
BaseConfig
17+
18+
GenesisID *core.ID `json:"genesisID"`
19+
ProfileNonce *big.Int `json:"profileNonce"`
20+
21+
AuthClaim *core.Claim `json:"authClaim"`
22+
23+
AuthClaimIncMtp *merkletree.Proof `json:"authClaimIncMtp"`
24+
AuthClaimNonRevMtp *merkletree.Proof `json:"authClaimNonRevMtp"`
25+
TreeState TreeState `json:"treeState"`
26+
27+
GISTProof GISTProof `json:"gistProof"`
28+
29+
Signature *babyjub.Signature `json:"signature"`
30+
Challenge *big.Int `json:"challenge"`
31+
}
32+
33+
func (a AuthV3Inputs) Validate() error {
34+
35+
if a.GenesisID == nil {
36+
return errors.New(ErrorEmptyID)
37+
}
38+
39+
if a.AuthClaimIncMtp == nil {
40+
return errors.New(ErrorEmptyAuthClaimProof)
41+
}
42+
43+
if a.AuthClaimNonRevMtp == nil {
44+
return errors.New(ErrorEmptyAuthClaimNonRevProof)
45+
}
46+
47+
if a.GISTProof.Proof == nil {
48+
return errors.New(ErrorEmptyGISTProof)
49+
}
50+
51+
if a.Signature == nil {
52+
return errors.New(ErrorEmptyChallengeSignature)
53+
}
54+
55+
if a.Challenge == nil {
56+
return errors.New(ErrorEmptyChallenge)
57+
}
58+
59+
return nil
60+
}
61+
62+
// InputsMarshal returns Circom private inputs for auth.circom
63+
func (a AuthV3Inputs) InputsMarshal() ([]byte, error) {
64+
65+
if err := a.Validate(); err != nil {
66+
return nil, err
67+
}
68+
69+
s := authCircuitInputs{
70+
GenesisID: a.GenesisID.BigInt().String(),
71+
ProfileNonce: a.ProfileNonce.String(),
72+
AuthClaim: a.AuthClaim,
73+
AuthClaimMtp: merkletree.CircomSiblingsFromSiblings(a.AuthClaimIncMtp.AllSiblings(),
74+
a.GetMTLevel()-1),
75+
AuthClaimNonRevMtp: merkletree.CircomSiblingsFromSiblings(a.AuthClaimNonRevMtp.AllSiblings(),
76+
a.GetMTLevel()-1),
77+
Challenge: a.Challenge.String(),
78+
ChallengeSignatureR8X: a.Signature.R8.X.String(),
79+
ChallengeSignatureR8Y: a.Signature.R8.Y.String(),
80+
ChallengeSignatureS: a.Signature.S.String(),
81+
ClaimsTreeRoot: a.TreeState.ClaimsRoot,
82+
RevTreeRoot: a.TreeState.RevocationRoot,
83+
RootsTreeRoot: a.TreeState.RootOfRoots,
84+
State: a.TreeState.State,
85+
GISTRoot: a.GISTProof.Root,
86+
GISTMtp: merkletree.CircomSiblingsFromSiblings(a.GISTProof.Proof.AllSiblings(),
87+
a.GetMTLevelOnChain()-1),
88+
}
89+
90+
nodeAuxAuth := GetNodeAuxValue(a.AuthClaimNonRevMtp)
91+
s.AuthClaimNonRevMtpAuxHi = nodeAuxAuth.key
92+
s.AuthClaimNonRevMtpAuxHv = nodeAuxAuth.value
93+
s.AuthClaimNonRevMtpNoAux = nodeAuxAuth.noAux
94+
95+
gistNodeAux := GetNodeAuxValue(a.GISTProof.Proof)
96+
s.GISTMtpAuxHi = gistNodeAux.key
97+
s.GISTMtpAuxHv = gistNodeAux.value
98+
s.GISTMtpNoAux = gistNodeAux.noAux
99+
100+
return json.Marshal(s)
101+
}
102+
103+
// GetPublicStatesInfo returns states and gists information,
104+
// implements PublicStatesInfoProvider interface
105+
func (a AuthV3Inputs) GetPublicStatesInfo() (StatesInfo, error) {
106+
107+
if err := a.Validate(); err != nil {
108+
return StatesInfo{}, err
109+
}
110+
111+
userID, err := core.ProfileID(*a.GenesisID, a.ProfileNonce)
112+
if err != nil {
113+
return StatesInfo{}, err
114+
}
115+
return StatesInfo{
116+
States: []State{},
117+
Gists: []Gist{
118+
{
119+
ID: userID,
120+
Root: *a.GISTProof.Root,
121+
},
122+
},
123+
}, nil
124+
}
125+
126+
// AuthV3PubSignals authV3.circom/authV3-8-32.circom public signals
127+
type AuthV3PubSignals struct {
128+
UserID *core.ID `json:"userID"`
129+
Challenge *big.Int `json:"challenge"`
130+
GISTRoot *merkletree.Hash `json:"GISTRoot"`
131+
}
132+
133+
// PubSignalsUnmarshal unmarshal authV3.circom/authV3-8-32.circom public inputs to AuthPubSignals
134+
func (a *AuthV3PubSignals) PubSignalsUnmarshal(data []byte) error {
135+
var sVals []string
136+
err := json.Unmarshal(data, &sVals)
137+
if err != nil {
138+
return err
139+
}
140+
141+
if len(sVals) != 3 {
142+
return fmt.Errorf("invalid number of Output values expected {%d} got {%d} ", 3, len(sVals))
143+
}
144+
145+
if a.UserID, err = idFromIntStr(sVals[0]); err != nil {
146+
return err
147+
}
148+
149+
var ok bool
150+
if a.Challenge, ok = big.NewInt(0).SetString(sVals[1], 10); !ok {
151+
return fmt.Errorf("invalid challenge value: '%s'", sVals[0])
152+
}
153+
154+
if a.GISTRoot, err = merkletree.NewHashFromString(sVals[2]); err != nil {
155+
return err
156+
}
157+
158+
return nil
159+
}
160+
161+
// GetObjMap returns AuthPubSignals as a map
162+
func (a AuthV3PubSignals) GetObjMap() map[string]interface{} {
163+
return toMap(a)
164+
}
165+
166+
func (a AuthV3PubSignals) GetStatesInfo() (StatesInfo, error) {
167+
if a.UserID == nil {
168+
return StatesInfo{}, errors.New(ErrorEmptyID)
169+
}
170+
if a.GISTRoot == nil {
171+
return StatesInfo{}, errors.New(ErrorEmptyStateHash)
172+
}
173+
return StatesInfo{
174+
States: []State{},
175+
Gists: []Gist{{ID: *a.UserID, Root: *a.GISTRoot}},
176+
}, nil
177+
}

authV3_test.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package circuits
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"math/big"
7+
"testing"
8+
9+
it "github.com/iden3/go-circuits/v2/testing"
10+
core "github.com/iden3/go-iden3-core/v2"
11+
"github.com/iden3/go-merkletree-sql/v2"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func authV3Inputs(t testing.TB, isAuthV3_8_32 bool) AuthV3Inputs {
16+
ctx := context.Background()
17+
challenge := big.NewInt(10)
18+
19+
// generate identity
20+
user := it.NewIdentity(t, userPK)
21+
nonce := big.NewInt(0)
22+
23+
user2 := it.NewIdentity(t, issuerPK)
24+
25+
// generate gist tree
26+
gTree := it.GISTTree(ctx)
27+
28+
err := gTree.Add(ctx, user2.ID.BigInt(), user2.State(t).BigInt())
29+
require.NoError(t, err)
30+
31+
// prepare inputs
32+
gistProof, _, err := gTree.GenerateProof(ctx, user.ID.BigInt(), nil)
33+
require.NoError(t, err)
34+
35+
authClaimIncMTP, _ := user.ClaimMTPRaw(t, user.AuthClaim)
36+
37+
authClaimNonRevMTP, _ := user.ClaimRevMTPRaw(t, user.AuthClaim)
38+
require.NoError(t, err)
39+
40+
signature, err := user.SignBBJJ(challenge.Bytes())
41+
require.NoError(t, err)
42+
43+
inputs := AuthV3Inputs{
44+
GenesisID: &user.ID,
45+
ProfileNonce: nonce,
46+
AuthClaim: user.AuthClaim,
47+
AuthClaimIncMtp: authClaimIncMTP,
48+
AuthClaimNonRevMtp: authClaimNonRevMTP,
49+
TreeState: GetTreeState(t, user),
50+
GISTProof: GISTProof{
51+
Root: gTree.Root(),
52+
Proof: gistProof,
53+
},
54+
Signature: signature,
55+
Challenge: challenge,
56+
}
57+
58+
if isAuthV3_8_32 {
59+
inputs.BaseConfig = BaseConfig{MTLevel: 8, MTLevelOnChain: 32}
60+
}
61+
return inputs
62+
}
63+
64+
func TestAuthV3Inputs_InputsMarshal(t *testing.T) {
65+
inputs := authV3Inputs(t, false)
66+
circuitInputJSON, err := inputs.InputsMarshal()
67+
require.NoError(t, err)
68+
69+
exp := it.TestData(t, "authV3_inputs", string(circuitInputJSON), *generate)
70+
require.JSONEq(t, exp, string(circuitInputJSON))
71+
}
72+
73+
func TestAuthV3_8_32Inputs_InputsMarshal(t *testing.T) {
74+
inputs := authV3Inputs(t, true)
75+
circuitInputJSON, err := inputs.InputsMarshal()
76+
require.NoError(t, err)
77+
78+
exp := it.TestData(t, "authV3-8-32_inputs", string(circuitInputJSON), *generate)
79+
require.JSONEq(t, exp, string(circuitInputJSON))
80+
}
81+
82+
func TestAuthV3Inputs_GetPublicStatesInfo(t *testing.T) {
83+
inputs := authV3Inputs(t, false)
84+
statesInfo, err := inputs.GetPublicStatesInfo()
85+
require.NoError(t, err)
86+
87+
statesInfoJsonBytes, err := json.Marshal(statesInfo)
88+
require.NoError(t, err)
89+
90+
want := `{
91+
"states":[],
92+
"gists":[
93+
{
94+
"id":"26109404700696283154998654512117952420503675471097392618762221546565140481",
95+
"root":"11098939821764568131087645431296528907277253709936443029379587475821759259406"
96+
}
97+
]
98+
}`
99+
100+
require.JSONEq(t, want, string(statesInfoJsonBytes))
101+
}
102+
103+
func TestAuthV3_8_32Inputs_GetPublicStatesInfo(t *testing.T) {
104+
inputs := authV3Inputs(t, true)
105+
statesInfo, err := inputs.GetPublicStatesInfo()
106+
require.NoError(t, err)
107+
108+
statesInfoJsonBytes, err := json.Marshal(statesInfo)
109+
require.NoError(t, err)
110+
111+
want := `{
112+
"states":[],
113+
"gists":[
114+
{
115+
"id":"26109404700696283154998654512117952420503675471097392618762221546565140481",
116+
"root":"11098939821764568131087645431296528907277253709936443029379587475821759259406"
117+
}
118+
]
119+
}`
120+
121+
require.JSONEq(t, want, string(statesInfoJsonBytes))
122+
}
123+
124+
func TestAuthV3Circuit_CircuitUnmarshal(t *testing.T) {
125+
// generate mock Data.
126+
intID, b := new(big.Int).SetString("19224224881555258540966250468059781351205177043309252290095510834143232000",
127+
10)
128+
require.True(t, b)
129+
identifier, err := core.IDFromInt(intID)
130+
require.NoError(t, err)
131+
132+
challenge := big.NewInt(1)
133+
134+
stateInt, b := new(big.Int).SetString(
135+
"18656147546666944484453899241916469544090258810192803949522794490493271005313",
136+
10)
137+
require.True(t, b)
138+
state, err := merkletree.NewHashFromBigInt(stateInt)
139+
require.NoError(t, err)
140+
141+
out := []string{identifier.BigInt().String(), challenge.String(), state.BigInt().String()}
142+
bytesOut, err := json.Marshal(out)
143+
require.NoError(t, err)
144+
145+
ao := AuthV3PubSignals{}
146+
err = ao.PubSignalsUnmarshal(bytesOut)
147+
require.NoError(t, err)
148+
require.Equal(t, challenge, ao.Challenge)
149+
require.Equal(t, state, ao.GISTRoot)
150+
require.Equal(t, &identifier, ao.UserID)
151+
152+
statesInfo, err := ao.GetStatesInfo()
153+
require.NoError(t, err)
154+
wantStatesInfo := StatesInfo{
155+
States: []State{},
156+
Gists: []Gist{
157+
{
158+
ID: idFromInt("19224224881555258540966250468059781351205177043309252290095510834143232000"),
159+
Root: hashFromInt("18656147546666944484453899241916469544090258810192803949522794490493271005313"),
160+
},
161+
},
162+
}
163+
j, err := json.Marshal(statesInfo)
164+
require.NoError(t, err)
165+
require.Equal(t, wantStatesInfo, statesInfo, string(j))
166+
}

0 commit comments

Comments
 (0)