Skip to content

Commit

Permalink
Another implemaentation of GetPublicStatesInfo on InputsSignals inste…
Browse files Browse the repository at this point in the history
…ad of on PubSignals (#90)

Add GetPublicStatesInfo on Inputs
  • Loading branch information
olomix authored Jan 16, 2025
1 parent 2bd2c4b commit 51815c3
Show file tree
Hide file tree
Showing 19 changed files with 1,009 additions and 117 deletions.
45 changes: 35 additions & 10 deletions authV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,23 +135,35 @@ func (a AuthV2Inputs) InputsMarshal() ([]byte, error) {
return json.Marshal(s)
}

// AuthV2PubSignals auth.circom public signals
type AuthV2PubSignals struct {
UserID *core.ID `json:"userID"`
Challenge *big.Int `json:"challenge"`
GISTRoot *merkletree.Hash `json:"GISTRoot"`
}
// GetPublicStatesInfo returns states and gists information,
// implements PublicStatesInfoProvider interface
func (a AuthV2Inputs) GetPublicStatesInfo() (StatesInfo, error) {

func (ao *AuthV2PubSignals) GetStatesInfo() StatesInfo {
if err := a.Validate(); err != nil {
return StatesInfo{}, err
}

userID, err := core.ProfileID(*a.GenesisID, a.ProfileNonce)
if err != nil {
return StatesInfo{}, err
}
return StatesInfo{
States: []State{},
Gists: []Gist{
{
ID: ao.UserID,
Root: ao.GISTRoot,
ID: userID,
Root: *a.GISTProof.Root,
},
},
}
}, nil
}


// AuthV2PubSignals auth.circom public signals
type AuthV2PubSignals struct {
UserID *core.ID `json:"userID"`
Challenge *big.Int `json:"challenge"`
GISTRoot *merkletree.Hash `json:"GISTRoot"`
}

// PubSignalsUnmarshal unmarshal auth.circom public inputs to AuthPubSignals
Expand Down Expand Up @@ -186,3 +198,16 @@ func (a *AuthV2PubSignals) PubSignalsUnmarshal(data []byte) error {
func (a AuthV2PubSignals) GetObjMap() map[string]interface{} {
return toMap(a)
}

func (a AuthV2PubSignals) GetStatesInfo() (StatesInfo, error) {
if a.UserID == nil {
return StatesInfo{}, errors.New(ErrorEmptyID)
}
if a.GISTRoot == nil {
return StatesInfo{}, errors.New(ErrorEmptyStateHash)
}
return StatesInfo{
States: []State{},
Gists: []Gist{{ID: *a.UserID, Root: *a.GISTRoot}},
}, nil
}
7 changes: 7 additions & 0 deletions authV2_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ func (j *jsonInt) MarshalJSON() ([]byte, error) {
return json.Marshal((*big.Int)(j).String())
}

func (j *jsonInt) BigInt() *big.Int {
if j == nil {
return nil
}
return (*big.Int)(j)
}

type jsonSignature babyjub.Signature

func (s *jsonSignature) UnmarshalJSON(bytes []byte) error {
Expand Down
67 changes: 52 additions & 15 deletions authV2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ import (
it "github.com/iden3/go-circuits/v2/testing"
core "github.com/iden3/go-iden3-core/v2"
"github.com/iden3/go-merkletree-sql/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAuthV2Inputs_InputsMarshal(t *testing.T) {

func authV2Inputs(t testing.TB) AuthV2Inputs {
ctx := context.Background()
challenge := big.NewInt(10)

Expand Down Expand Up @@ -42,7 +40,7 @@ func TestAuthV2Inputs_InputsMarshal(t *testing.T) {
signature, err := user.SignBBJJ(challenge.Bytes())
require.NoError(t, err)

inputs := AuthV2Inputs{
return AuthV2Inputs{
GenesisID: &user.ID,
ProfileNonce: nonce,
AuthClaim: user.AuthClaim,
Expand All @@ -56,15 +54,39 @@ func TestAuthV2Inputs_InputsMarshal(t *testing.T) {
Signature: signature,
Challenge: challenge,
}
}

func TestAuthV2Inputs_InputsMarshal(t *testing.T) {
inputs := authV2Inputs(t)
circuitInputJSON, err := inputs.InputsMarshal()
assert.Nil(t, err)
require.NoError(t, err)

//t.Log(string(circuitInputJSON))
exp := it.TestData(t, "authV2_inputs", string(circuitInputJSON), *generate)
require.JSONEq(t, exp, string(circuitInputJSON))
}

func TestAuthV2Inputs_GetPublicStatesInfo(t *testing.T) {
inputs := authV2Inputs(t)
statesInfo, err := inputs.GetPublicStatesInfo()
require.NoError(t, err)

statesInfoJsonBytes, err := json.Marshal(statesInfo)
require.NoError(t, err)

want := `{
"states":[],
"gists":[
{
"id":"26109404700696283154998654512117952420503675471097392618762221546565140481",
"root":"11098939821764568131087645431296528907277253709936443029379587475821759259406"
}
]
}`

require.JSONEq(t, want, string(statesInfoJsonBytes))
}

func TestAuthV2Inputs_InputsMarshal_fromJson(t *testing.T) {
t.Skip("skipping TODO: finish test")
auth2_json := `{
Expand Down Expand Up @@ -138,32 +160,47 @@ func TestAuthV2Circuit_CircuitUnmarshal(t *testing.T) {
// generate mock Data.
intID, b := new(big.Int).SetString("19224224881555258540966250468059781351205177043309252290095510834143232000",
10)
assert.True(t, b)
require.True(t, b)
identifier, err := core.IDFromInt(intID)
assert.Nil(t, err)
require.NoError(t, err)

challenge := big.NewInt(1)

stateInt, b := new(big.Int).SetString(
"18656147546666944484453899241916469544090258810192803949522794490493271005313",
10)
assert.True(t, b)
require.True(t, b)
state, err := merkletree.NewHashFromBigInt(stateInt)
assert.NoError(t, err)
require.NoError(t, err)

out := []string{identifier.BigInt().String(), challenge.String(), state.BigInt().String()}
bytesOut, err := json.Marshal(out)
assert.NoError(t, err)
require.NoError(t, err)

ao := AuthV2PubSignals{}
err = ao.PubSignalsUnmarshal(bytesOut)
assert.NoError(t, err)
assert.Equal(t, challenge, ao.Challenge)
assert.Equal(t, state, ao.GISTRoot)
assert.Equal(t, &identifier, ao.UserID)
require.NoError(t, err)
require.Equal(t, challenge, ao.Challenge)
require.Equal(t, state, ao.GISTRoot)
require.Equal(t, &identifier, ao.UserID)

statesInfo, err := ao.GetStatesInfo()
require.NoError(t, err)
wantStatesInfo := StatesInfo{
States: []State{},
Gists: []Gist{
{
ID: idFromInt("19224224881555258540966250468059781351205177043309252290095510834143232000"),
Root: hashFromInt("18656147546666944484453899241916469544090258810192803949522794490493271005313"),
},
},
}
j, err := json.Marshal(statesInfo)
require.NoError(t, err)
require.Equal(t, wantStatesInfo, statesInfo, string(j))
}

func GetTreeState(t *testing.T, it *it.IdentityTest) TreeState {
func GetTreeState(t testing.TB, it *it.IdentityTest) TreeState {
return TreeState{
State: it.State(t),
ClaimsRoot: it.Clt.Root(),
Expand Down
103 changes: 94 additions & 9 deletions circuits.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package circuits

import (
"bytes"
"encoding/json"
"reflect"
"sync"

Expand Down Expand Up @@ -198,27 +200,110 @@ type PubSignals interface {
PubSignalsMapper
}

// StateInfoPubSignals interface implemented by types that can return states info
type StateInfoPubSignals interface {
GetStatesInfo() StatesInfo
// PublicStatesInfoProvider interface should be implemented by Inputs types that
// can return public states info
type PublicStatesInfoProvider interface {
GetPublicStatesInfo() (StatesInfo, error)
}

// StatesInfoProvider interface should be implemented by PubSignals types that
// can return states info
type StatesInfoProvider interface {
GetStatesInfo() (StatesInfo, error)
}

// StatesInfo struct. A collection of states and gists
type StatesInfo struct {
States []State
Gists []Gist
States []State `json:"states"`
Gists []Gist `json:"gists"`
}

// State information
type State struct {
ID *core.ID
State *merkletree.Hash
ID core.ID `json:"id"`
State merkletree.Hash `json:"state"`
}

func (s *State) UnmarshalJSON(i []byte) error {
var j struct {
ID *jsonInt `json:"id"`
State *jsonInt `json:"state"`
}
err := json.Unmarshal(i, &j)
if err != nil {
return err
}

if j.ID == nil {
return errors.New("id is nil")
}
s.ID, err = core.IDFromInt(j.ID.BigInt())
if err != nil {
return err
}

h, err := merkletree.NewHashFromBigInt(j.State.BigInt())
if err != nil {
return err
}
s.State = *h

return nil
}

func (s State) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
b.Grow(256) // 20 + 2*78 + padding ≈ 256
b.Write([]byte(`{"id":"`))
b.Write([]byte(s.ID.BigInt().String()))
b.Write([]byte(`","state":"`))
b.Write([]byte(s.State.BigInt().String()))
b.Write([]byte(`"}`))
return b.Bytes(), nil
}

// Gist information
type Gist struct {
ID *core.ID
Root *merkletree.Hash
ID core.ID `json:"id"`
Root merkletree.Hash `json:"root"`
}

func (g *Gist) UnmarshalJSON(i []byte) error {
var j struct {
ID *jsonInt `json:"id"`
Root *jsonInt `json:"root"`
}
err := json.Unmarshal(i, &j)
if err != nil {
return err
}

if j.ID == nil {
return errors.New("id is nil")
}
g.ID, err = core.IDFromInt(j.ID.BigInt())
if err != nil {
return err
}

h, err := merkletree.NewHashFromBigInt(j.Root.BigInt())
if err != nil {
return err
}
g.Root = *h

return nil
}

func (g Gist) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
b.Grow(256) // 20 + 2*78 + padding ≈ 256
b.Write([]byte(`{"id":"`))
b.Write([]byte(g.ID.BigInt().String()))
b.Write([]byte(`","root":"`))
b.Write([]byte(g.Root.BigInt().String()))
b.Write([]byte(`"}`))
return b.Bytes(), nil
}

// KeyLoader interface, if key should be fetched from file system, CDN, IPFS etc,
Expand Down
53 changes: 53 additions & 0 deletions circuits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
core "github.com/iden3/go-iden3-core/v2"
"github.com/iden3/go-merkletree-sql/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestUnmarshalCircuitOutput(t *testing.T) {
Expand Down Expand Up @@ -39,3 +40,55 @@ func TestUnmarshalCircuitOutput_Err(t *testing.T) {

assert.Equal(t, err, ErrorCircuitIDNotFound)
}

func TestGistJsonMarshallers(t *testing.T) {
var in Gist
var err error
in.ID, err = core.IDFromString("tQomzpDTB6x4EJUaiwk153FVi96jeNfP9WjKp9xys")
require.NoError(t, err)

h, err := merkletree.NewHashFromString("11098939821764568131087645431296528907277253709936443029379587475821759259406")
require.NoError(t, err)
in.Root = *h

wantJson := `{
"id": "26109404700696283154998654512117952420503675471097392618762221546565140481",
"root": "11098939821764568131087645431296528907277253709936443029379587475821759259406"
}`

inJsonBytes, err := json.Marshal(in)
require.NoError(t, err)

require.JSONEq(t, wantJson, string(inJsonBytes))

var out Gist
err = json.Unmarshal(inJsonBytes, &out)
require.NoError(t, err)
require.Equal(t, in, out)
}

func TestStateJsonMarshallers(t *testing.T) {
var in State
var err error
in.ID, err = core.IDFromString("tQomzpDTB6x4EJUaiwk153FVi96jeNfP9WjKp9xys")
require.NoError(t, err)

h, err := merkletree.NewHashFromString("11098939821764568131087645431296528907277253709936443029379587475821759259406")
require.NoError(t, err)
in.State = *h

wantJson := `{
"id": "26109404700696283154998654512117952420503675471097392618762221546565140481",
"state": "11098939821764568131087645431296528907277253709936443029379587475821759259406"
}`

inJsonBytes, err := json.Marshal(in)
require.NoError(t, err)

require.JSONEq(t, wantJson, string(inJsonBytes))

var out State
err = json.Unmarshal(inJsonBytes, &out)
require.NoError(t, err)
require.Equal(t, in, out)
}
Loading

0 comments on commit 51815c3

Please sign in to comment.