diff --git a/.gitignore b/.gitignore index 78d053ff..52f57eab 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,5 @@ build .idea .vscode .DS_Store -powersOfTau28_hez_final_17.ptau +powersOfTau28_hez_final_*.ptau testvectorgen/**/testdata \ No newline at end of file diff --git a/README.md b/README.md index 0118d5ea..5aefdd5c 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,19 @@ The circuits of this repository are compatible with the [go-iden3-core implement # Building and trusted setup -First install the npm dependencies: +1. Install the npm dependencies: ```bash npm ci ``` -Then build the circuit and do the "trusted" setup: +2. Download corresponding powersOfTau file to be able to compile circuits: + +```bash +wget https://storage.googleapis.com/zkevm/ptau/powersOfTau28_hez_final_18.ptau +``` + +3. Then build the circuit and do the "trusted" setup: ```bash ./compile-circuit.sh CIRCUIT_PATH PTAU_FILE_PATH @@ -21,8 +27,8 @@ Then build the circuit and do the "trusted" setup: Examples: ```bash -./compile-circuit.sh circuits/auth.circom build/powersOfTau28_hez_final_16.ptau -./compile-circuit.sh circuits/stateTransition.circom build/powersOfTau28_hez_final_16.ptau +./compile-circuit.sh circuits/auth.circom powersOfTau28_hez_final_18.ptau +./compile-circuit.sh circuits/stateTransition.circom powersOfTau28_hez_final_18.ptau ``` ## Work with `s3_util.js` script @@ -78,5 +84,29 @@ node s3_util.js rm v1 ... ``` +## Generate data folders with JSON files with proofs for contracts repo validators testing + +Scripts for generating the data with proofs for contracts repo for testing are placed in folders `testvectorgen` and `update-contract-data`. +Example: Generate data for v3 tests in contracts repo (you should have the repo cloned in local) + +1. Go to folder `testvectorgen/contract_data/v3` + ```bash + cd testvectorgen/contract_data/v3 + ``` +2. Generate executable for v3 + ```bash + go test -c -o v3_test + ``` +3. Execute inputs data generation for generating proofs + ```bash + ./v3_test + ``` +4. You will see a folder `testdata` generated in the same folder with files with inputs for generating the different proofs. +5. In root folder of the repo you can execute the Node script to generate the JSON files with proofs that will be copied to contracts repo + ```bash + node update-contract-data/update-contract-data-v3.js + ``` +6. You will see in your `../contracts/test/validators/v3/data` and `../contracts/test/validators/common-data` the JSON files generated with the proofs needed for the validators tests in contracts. + ## Security Audits 1. [Trail of Bits](https://github.com/trailofbits/publications/tree/master/reviews) has performed a security audit of our circuits and compiled a report on May 3, 2024: [2024-05-polygonlabs-iden3circuits-securityreview.pdf](https://raw.githubusercontent.com/iden3/audits/adc81d1bce9a7bde9577eb4389998d60cfac9619/circuits/2024-05-polygonlabs-iden3circuits-securityreview.pdf) \ No newline at end of file diff --git a/compile-circuit.sh b/compile-circuit.sh index d47535a5..4ad37b55 100755 --- a/compile-circuit.sh +++ b/compile-circuit.sh @@ -51,7 +51,7 @@ compile_and_ts() { if [ "$#" -ne 2 ] then echo "Usage: $0 CIRCUIT_PATH $1 PTAU_PATH">&2 - echo "Example: ./compile-circuit.sh example.circom powersOfTau28_hez_final_15.ptau" >&2 + echo "Example: ./compile-circuit.sh example.circom powersOfTau28_hez_final_18.ptau" >&2 exit 1 fi diff --git a/testvectorgen/auth/authV3_test.go b/testvectorgen/auth/authV3_test.go index 5585068a..246c22d5 100644 --- a/testvectorgen/auth/authV3_test.go +++ b/testvectorgen/auth/authV3_test.go @@ -102,8 +102,8 @@ func generateAuthTestData(t *testing.T, profile, genesis, isSecondAuthClaim bool nonce := big.NewInt(0) - challenge := big.NewInt(12345) - + challenge, ok := new(big.Int).SetString("5212973139745638668633720237501954966656555739014896868936311397139229290378", 10) + require.True(t, ok) user := utils.NewIdentity(t, userPK) var err error @@ -117,7 +117,6 @@ func generateAuthTestData(t *testing.T, profile, genesis, isSecondAuthClaim bool gisTree, err := merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), 40) require.Nil(t, err) - gisTree.Add(context.Background(), big.NewInt(1), big.NewInt(1)) if genesis == false { // extract pubKey @@ -154,7 +153,7 @@ func generateAuthTestData(t *testing.T, profile, genesis, isSecondAuthClaim bool require.NoError(t, err) gistRoot := gisTree.Root() - gistProof, gistNodAux := utils.PrepareProof(gistProofRaw, utils.GistLevels) + gistProof, gistNodAux := utils.PrepareProof(gistProofRaw, utils.OnChainLevels) inputs := AuthV3Inputs{ UserGenesisID: user.ID.BigInt().String(), diff --git a/testvectorgen/contract_data/v3-16-16-64-16-32/v3_test.go b/testvectorgen/contract_data/v3-16-16-64-16-32/v3_test.go new file mode 100644 index 00000000..36049fb1 --- /dev/null +++ b/testvectorgen/contract_data/v3-16-16-64-16-32/v3_test.go @@ -0,0 +1,759 @@ +package contractdata + +import ( + "context" + "encoding/json" + "math/big" + "strconv" + "testing" + + "test/utils" + + "github.com/ethereum/go-ethereum/common" + core "github.com/iden3/go-iden3-core/v2" + "github.com/iden3/go-iden3-crypto/babyjub" + "github.com/iden3/go-iden3-crypto/poseidon" + "github.com/iden3/go-merkletree-sql/v2" + "github.com/iden3/go-merkletree-sql/v2/db/memory" + "github.com/iden3/go-schema-processor/v2/merklize" + "github.com/iden3/go-schema-processor/v2/verifiable" + "github.com/stretchr/testify/require" +) + +const ( + ethAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + UserPK = "28156abe7fe2fd433dc9df969286b96666489bac508612d0e16593e944c4f69e" + IssuerPK = "28156abe7fe2fd433dc9df969286b96666489bac508612d0e16593e944c4f69d" + timestamp = "1642074362" + requestID = "32" +) + +type StateTransitionInputs struct { + AuthClaim *core.Claim `json:"authClaim"` + AuthClaimMtp []string `json:"authClaimMtp"` + AuthClaimNonRevMtp []string `json:"authClaimNonRevMtp"` + AuthClaimNonRevMtpAuxHi string `json:"authClaimNonRevMtpAuxHi"` + AuthClaimNonRevMtpAuxHv string `json:"authClaimNonRevMtpAuxHv"` + AuthClaimNonRevMtpNoAux string `json:"authClaimNonRevMtpNoAux"` + ClaimsTreeRoot string `json:"claimsTreeRoot"` + IsOldStateGenesis string `json:"isOldStateGenesis"` + NewUserState string `json:"newUserState"` + OldUserState string `json:"oldUserState"` + RevTreeRoot string `json:"revTreeRoot"` + RootsTreeRoot string `json:"rootsTreeRoot"` + SignatureR8X string `json:"signatureR8x"` + SignatureR8Y string `json:"signatureR8y"` + SignatureS string `json:"signatureS"` + UserID string `json:"userID"` + NewAuthClaimMtp []string `json:"newAuthClaimMtp"` + NewClaimsTreeRoot string `json:"newClaimsTreeRoot"` + NewRevTreeRoot string `json:"newRevTreeRoot"` + NewRootsTreeRoot string `json:"newRootsTreeRoot"` +} + +type StateTransitionOutputs struct { + ID string `json:"userID"` + NewUserState string `json:"newUserState"` + OldUserState string `json:"oldUserState"` + IsOldStateGenesis string `json:"isOldStateGenesis"` +} + +type TestDataStateTransition struct { + Desc string `json:"desc"` + In StateTransitionInputs `json:"inputs"` + Out StateTransitionOutputs `json:"expOut"` +} + +type gistData struct { + id *big.Int + state *big.Int +} + +func Test_Generate_Test_CasesV3(t *testing.T) { + + // genesis => first => second + issuerId, issuerFirstState := generateStateTransitionData(t, false, IssuerPK, UserPK, "Issuer from genesis to first state transition", "v3-16-16-64-16-32/issuer_from_genesis_state_to_first_transition_v3", true, false) + userId, userFirstState := generateStateTransitionData(t, false, UserPK, IssuerPK, "User from genesis transition", "v3-16-16-64-16-32/user_from_genesis_state_to_first_transition_v3", false, false) + + _, issuerSecondState := generateStateTransitionData(t, true, IssuerPK, UserPK, "Issuer from first to second transition", "v3-16-16-64-16-32/issuer_from_first_state_to_second_transition_v3", true, false) + _, userSecondState := generateStateTransitionData(t, true, UserPK, IssuerPK, "User from first to second transition", "v3-16-16-64-16-32/user_from_first_state_to_second_transition_v3", false, false) + + _, issuerAuthDisabledFirstState := generateStateTransitionData(t, false, IssuerPK, UserPK, "Issuer from genesis to first state transition auth disabled", "v3-16-16-64-16-32/issuer_from_genesis_state_to_first_auth_disabled_transition_v3", false, true) + + generateData(t, "BJJ: Issuer first state / user - genesis state", []*gistData{ + {issuerId, issuerFirstState}, + }, false, false, false, false, "v3-16-16-64-16-32/valid_bjj_user_genesis_v3", verifiable.BJJSignatureProofType, 1) + + generateData(t, "BJJ: Issuer first state / user first state - valid proof", []*gistData{ + {issuerId, issuerFirstState}, + {userId, userFirstState}, + }, true, false, false, false, "v3-16-16-64-16-32/valid_bjj_user_first_v3", verifiable.BJJSignatureProofType, 1) + + generateData(t, "BJJ: Issuer second state / user first state - valid proof", []*gistData{ + {userId, userFirstState}, + {issuerId, issuerSecondState}, + }, true, false, false, true, "v3-16-16-64-16-32/valid_bjj_user_first_issuer_second_v3", verifiable.BJJSignatureProofType, 1) + + generateData(t, "BJJ: Issuer first state / user second state - valid proof", []*gistData{ + {userId, userSecondState}, + {issuerId, issuerSecondState}, + }, true, true, false, false, "v3-16-16-64-16-32/valid_bjj_user_second_issuer_first_v3", verifiable.BJJSignatureProofType, 1) + + generateData(t, "BJJ: Issuer first state / user - genesis state - Auth Disabled", []*gistData{ + {issuerId, issuerAuthDisabledFirstState}, + }, false, false, false, false, "v3-16-16-64-16-32/valid_bjj_user_genesis_auth_disabled_v3", verifiable.BJJSignatureProofType, 0) + + // MTP Data: + generateData(t, "MTP: Issuer first state / user - genesis state", []*gistData{ + {issuerId, issuerFirstState}, + }, false, false, false, false, "v3-16-16-64-16-32/valid_mtp_user_genesis_v3", verifiable.Iden3SparseMerkleTreeProofType, 1) + + generateData(t, "MTP: Issuer first state / user first state - valid proof", []*gistData{ + {issuerId, issuerFirstState}, + {userId, userFirstState}, + }, true, false, false, false, "v3-16-16-64-16-32/valid_mtp_user_first_v3", verifiable.Iden3SparseMerkleTreeProofType, 1) + + generateData(t, "MTP: Issuer second state / user first state - valid proof", []*gistData{ + {userId, userFirstState}, + {issuerId, issuerSecondState}, + }, true, false, false, true, "v3-16-16-64-16-32/valid_mtp_user_first_issuer_second_v3", verifiable.Iden3SparseMerkleTreeProofType, 1) + + generateData(t, "MTP: Issuer first state / user second state - valid proof", []*gistData{ + {userId, userSecondState}, + {issuerId, issuerSecondState}, + }, true, true, false, false, "v3-16-16-64-16-32/valid_mtp_user_second_issuer_first_v3", verifiable.Iden3SparseMerkleTreeProofType, 1) + + generateData(t, "MTP: Issuer first state / user - genesis state - Auth Disabled", []*gistData{ + {issuerId, issuerAuthDisabledFirstState}, + }, false, false, false, false, "v3-16-16-64-16-32/valid_mtp_user_genesis_auth_disabled_v3", verifiable.Iden3SparseMerkleTreeProofType, 0) + + generateData(t, "BJJ: Issuer genesis state / user - first state", []*gistData{ + {userId, userFirstState}, + }, true, false, true, false, "v3-16-16-64-16-32/valid_bjj_user_first_issuer_genesis_v3", verifiable.BJJSignatureProofType, 1) +} + +func generateStateTransitionData(t *testing.T, nextState bool, primaryPK, secondaryPK, desc, fileName string, isSubjectIDProfile bool, isEthBased bool) (*big.Int, *big.Int) { + + var err error + primaryEntity := utils.NewIdentity(t, primaryPK) + + var secondaryEntity *utils.IdentityTest + + if !isEthBased { + secondaryEntity = utils.NewIdentity(t, secondaryPK) + } else { + // generate onchain identity + secondaryEntity = utils.NewEthereumBasedIdentity(t, ethAddress) + } + + isGenesis := "1" + // user + authMTProof := primaryEntity.AuthMTPStrign(t) + + authNonRevMTProof, nodeAuxNonRev := primaryEntity.ClaimRevMTPLevels(t, primaryEntity.AuthClaim, utils.IdOwnershipLevels2) + + oldState := primaryEntity.State(t) // old state is genesis + oldCltRoot := primaryEntity.Clt.Root().BigInt().String() + oldRevRoot := primaryEntity.Ret.Root().BigInt().String() + oldRotRoot := primaryEntity.Rot.Root().BigInt().String() + + //if genesis == false { + // extract pubKey + + subjectID := secondaryEntity.ID + if isSubjectIDProfile { + nonceSubject := big.NewInt(999) + subjectID, err = core.ProfileID(secondaryEntity.ID, nonceSubject) + require.NoError(t, err) + } + + _, secondaryEntityClaim := utils.DefaultJSONNormalUserClaim(t, subjectID) + primaryEntity.AddClaim(t, secondaryEntityClaim) + + if nextState { + isGenesis = "0" + // add claim just to change the state + + oldState = primaryEntity.State(t) // old state is genesis + oldCltRoot = primaryEntity.Clt.Root().BigInt().String() + oldRevRoot = primaryEntity.Ret.Root().BigInt().String() + oldRotRoot = primaryEntity.Rot.Root().BigInt().String() + authMTProof = primaryEntity.AuthMTPStrign(t) + + authNonRevMTProof, nodeAuxNonRev = primaryEntity.ClaimRevMTPLevels(t, primaryEntity.AuthClaim, utils.IdOwnershipLevels2) + primaryEntityClaim := utils.DefaultUserClaim(t, primaryEntity.ID, nil) + primaryEntity.AddClaim(t, primaryEntityClaim) + } + + hashOldAndNewStates, err := poseidon.Hash( + []*big.Int{oldState, primaryEntity.State(t)}) + require.NoError(t, err) + + sig := primaryEntity.Sign(hashOldAndNewStates) + require.NoError(t, err) + + newAuthMTProof := primaryEntity.AuthMTPStrign(t) + newCltRoot := primaryEntity.Clt.Root().BigInt().String() + newRevRoot := primaryEntity.Ret.Root().BigInt().String() + newRotRoot := primaryEntity.Rot.Root().BigInt().String() + + inputs := StateTransitionInputs{ + AuthClaim: primaryEntity.AuthClaim, + AuthClaimMtp: authMTProof, + AuthClaimNonRevMtp: authNonRevMTProof, + AuthClaimNonRevMtpAuxHi: nodeAuxNonRev.Key, + AuthClaimNonRevMtpAuxHv: nodeAuxNonRev.Value, + AuthClaimNonRevMtpNoAux: nodeAuxNonRev.NoAux, + ClaimsTreeRoot: oldCltRoot, + RevTreeRoot: oldRevRoot, + RootsTreeRoot: oldRotRoot, + IsOldStateGenesis: isGenesis, + NewUserState: primaryEntity.State(t).String(), + OldUserState: oldState.String(), + SignatureR8X: sig.R8.X.String(), + SignatureR8Y: sig.R8.Y.String(), + SignatureS: sig.S.String(), + UserID: primaryEntity.ID.BigInt().String(), + NewAuthClaimMtp: newAuthMTProof, + NewClaimsTreeRoot: newCltRoot, + NewRevTreeRoot: newRevRoot, + NewRootsTreeRoot: newRotRoot, + } + + out := StateTransitionOutputs{ + ID: primaryEntity.ID.BigInt().String(), + NewUserState: primaryEntity.State(t).String(), + OldUserState: oldState.String(), + IsOldStateGenesis: isGenesis, + } + + json_, err := json.Marshal(TestDataStateTransition{ + Desc: desc, + In: inputs, + Out: out, + }) + require.NoError(t, err) + + utils.SaveTestVector(t, fileName, string(json_)) + + return primaryEntity.ID.BigInt(), primaryEntity.State(t) +} + +func generateData(t *testing.T, desc string, gistData []*gistData, userFirstState bool, userSecondState bool, issuetGenesisState bool, issuerSecondState bool, fileName string, testProofType verifiable.ProofType, isBJJAuthEnabled int) { + + var linkNonce = "18" + var nullifierSessionID string = "1234569" + operator := utils.LT + isRevocationChecked := 1 // checked + isJSONLD := true // merklized for now + var err error + + const isRevoked = false + const isSubjectIDProfile = true + + valueInput := utils.PrepareStrArray([]string{"20010101"}, utils.MaxValueArraySize2) + + var user *utils.IdentityTest + + if isBJJAuthEnabled == 1 { + user = utils.NewIdentity(t, UserPK) + } else { + // generate onchain identity + user = utils.NewEthereumBasedIdentity(t, ethAddress) + nullifierSessionID = "0" + } + issuer := utils.NewIdentity(t, IssuerPK) + + userProfileID := user.ID + nonce := big.NewInt(0) + + subjectID := user.ID + + var nonceSubject = new(big.Int) + if isSubjectIDProfile && isBJJAuthEnabled == 1 { + nonceSubject = big.NewInt(999) + subjectID, err = core.ProfileID(user.ID, nonceSubject) + require.NoError(t, err) + } + + var claim *core.Claim + var mz *merklize.Merklizer + var claimPathMtp []string + var claimPathMtpNoAux, claimPathMtpAuxHi, claimPathMtpAuxHv, claimPathKey, claimPathValue, merklized string + var pathKey *big.Int + var slotIndex int + + if isJSONLD { + mz, claim = utils.DefaultJSONNormalUserClaim(t, subjectID) + path, err := merklize.NewPath( + "https://www.w3.org/2018/credentials#credentialSubject", + "https://github.com/iden3/claim-schema-vocab/blob/main/credentials/kyc.md#birthday") + require.NoError(t, err) + jsonP, value, err := mz.Proof(context.Background(), path) + require.NoError(t, err) + valueKey, err := value.MtEntry() + require.NoError(t, err) + claimPathValue = valueKey.String() + + var claimJSONLDProofAux utils.NodeAuxValue + claimPathMtp, claimJSONLDProofAux = utils.PrepareProof(jsonP, utils.ClaimLevels2) + claimPathMtpNoAux = claimJSONLDProofAux.NoAux + claimPathMtpAuxHi = claimJSONLDProofAux.Key + claimPathMtpAuxHv = claimJSONLDProofAux.Value + pathKey, err = path.MtEntry() + require.NoError(t, err) + claimPathKey = pathKey.String() + slotIndex = 0 + + //valueInput = utils.PrepareStrArray([]string{claimPathValue}, 64) + merklized = "1" + + } else { + claim = utils.DefaultUserClaim(t, subjectID, nil) + claimPathMtp = utils.PrepareStrArray([]string{}, utils.ClaimLevels2) + claimPathMtpNoAux = "0" + claimPathMtpAuxHi = "0" + claimPathMtpAuxHv = "0" + claimPathKey = "0" + claimPathValue = "0" + merklized = "0" + slotIndex = 2 + pathKey = big.NewInt(0) + } + + if userFirstState { + _, claim1 := utils.DefaultJSONNormalUserClaim(t, issuer.ID) + user.AddClaim(t, claim1) + + if userSecondState { + claim2 := utils.DefaultUserClaim(t, user.ID, nil) + user.AddClaim(t, claim2) + } + } + + if isRevoked { + revNonce := claim.GetRevocationNonce() + revNonceBigInt := new(big.Int).SetUint64(revNonce) + issuer.Ret.Add(context.Background(), revNonceBigInt, big.NewInt(0)) + } + + var issuerClaimMtp, issuerAuthClaimMtp, issuerAuthClaimNonRevMtp []string + var issuerClaimClaimsTreeRoot, issuerClaimRevTreeRoot, issuerClaimRootsTreeRoot *merkletree.Hash + var issuerClaimSignatureR8X, issuerClaimSignatureR8Y, issuerClaimSignatureS, + issuerAuthClaimNonRevMtpAuxHi, issuerAuthClaimNonRevMtpAuxHv, issuerAuthClaimNonRevMtpNoAux, + issuerClaimIdenState, proofType string + + var issuerAuthClaimsTreeRoot, issuerAuthRevTreeRoot, issuerAuthRootsTreeRoot string + var issuerAuthState string + var issuerAuthClaim *core.Claim + + issuerAuthClaimsTreeRoot = issuer.Clt.Root().BigInt().String() + issuerAuthRevTreeRoot = issuer.Ret.Root().BigInt().String() + issuerAuthRootsTreeRoot = issuer.Rot.Root().BigInt().String() + + issuerAuthState = issuer.State(t).String() + + issuerAuthClaimMtp, _ = issuer.ClaimMTPLevels(t, issuer.AuthClaim, utils.IssuerLevels2) + + if !issuetGenesisState { + issuer.AddClaim(t, claim) + } + + issuerClaimMtp, _ = issuer.ClaimMTPLevels(t, claim, utils.IssuerLevels2) + require.NoError(t, err) + issuerClaimIdenState = issuer.State(t).String() + + issuerClaimClaimsTreeRoot = issuer.Clt.Root() + issuerClaimRevTreeRoot = issuer.Ret.Root() + issuerClaimRootsTreeRoot = issuer.Rot.Root() + + // add another claim to issuer if it is a second state + if issuerSecondState { + primaryEntityClaim := utils.DefaultUserClaim(t, issuer.ID, nil) + issuer.AddClaim(t, primaryEntityClaim) + } + + // prove revocation on latest state of the issuer + issuerClaimNonRevMtp, issuerClaimNonRevAux := issuer.ClaimRevMTPLevels(t, claim, utils.IssuerLevels2) + + issuerAuthClaimNonRevMtp, issuerAuthClaimNodeAux := issuer.ClaimRevMTPLevels(t, issuer.AuthClaim, utils.IssuerLevels2) + issuerAuthClaimNonRevMtpNoAux = issuerAuthClaimNodeAux.NoAux + issuerAuthClaimNonRevMtpAuxHi = issuerAuthClaimNodeAux.Key + issuerAuthClaimNonRevMtpAuxHv = issuerAuthClaimNodeAux.Value + + if testProofType == verifiable.BJJSignatureProofType { + // Sig claim + claimSig := issuer.SignClaim(t, claim) + + issuerClaimSignatureR8X = claimSig.R8.X.String() + issuerClaimSignatureR8Y = claimSig.R8.Y.String() + issuerClaimSignatureS = claimSig.S.String() + + issuerAuthClaim = issuer.AuthClaim + + proofType = "1" + } else { + + issuerClaimSignatureR8X = "0" + issuerClaimSignatureR8Y = "0" + issuerClaimSignatureS = "0" + + issuerAuthClaimNonRevMtpAuxHi = "0" + issuerAuthClaimNonRevMtpAuxHv = "0" + issuerAuthClaimNonRevMtpNoAux = "0" + + issuerAuthClaimMtp = utils.PrepareStrArray([]string{}, utils.IssuerLevels2) + + issuerAuthClaim = &core.Claim{} + + issuerAuthClaimsTreeRoot = (&merkletree.HashZero).BigInt().String() + issuerAuthRevTreeRoot = (&merkletree.HashZero).BigInt().String() + issuerAuthRootsTreeRoot = (&merkletree.HashZero).BigInt().String() + + issuerAuthState = "0" + + slotIndex = 2 + proofType = "2" + } + + gisTree, err := merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), utils.OnChainLevels2) + require.Nil(t, err) + + for _, data := range gistData { + idPoseidonHash, _ := poseidon.Hash([]*big.Int{data.id}) + err = gisTree.Add(context.Background(), idPoseidonHash, data.state) + require.Nil(t, err) + } + + var authMTProof []string + var challenge *big.Int + var userAuthNonRevMTProof []string + var userNodeAuxNonRev utils.NodeAuxValue + var sig *babyjub.Signature + var gistRoot *merkletree.Hash + var gistProof []string + var gistNodeAux utils.NodeAuxValue + + addr := common.HexToAddress(ethAddress) + challenge = new(big.Int).SetBytes(merkletree.SwapEndianness(addr.Bytes())) + + // user + if isBJJAuthEnabled == 1 { + authMTProof = user.AuthMTPStrignLevels(t, utils.IdOwnershipLevels2) + userAuthNonRevMTProof, userNodeAuxNonRev = user.ClaimRevMTPLevels(t, user.AuthClaim, utils.IdOwnershipLevels2) + sig = user.Sign(challenge) + gistProofRaw, _, err := gisTree.GenerateProof(context.Background(), user.IDHash(t), nil) + require.NoError(t, err) + gistRoot = gisTree.Root() + gistProof, gistNodeAux = utils.PrepareProof(gistProofRaw, utils.OnChainLevels2) + + } else { + + emptyArr := make([]*merkletree.Hash, 0) + authMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IssuerLevels2) + userAuthNonRevMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IssuerLevels2) + userNodeAuxNonRev = utils.NodeAuxValue{ + Key: merkletree.HashZero.String(), + Value: merkletree.HashZero.String(), + NoAux: "0", + } + sig = &babyjub.Signature{ + R8: &babyjub.Point{ + X: new(big.Int), + Y: new(big.Int), + }, + S: new(big.Int), + } + + gistRoot = &merkletree.HashZero + gistProof = utils.PrepareSiblingsStr(emptyArr, utils.OnChainLevels2) + gistNodeAux = utils.NodeAuxValue{ + Key: merkletree.HashZero.String(), + Value: merkletree.HashZero.String(), + NoAux: "0", + } + + user.AuthClaim = &core.Claim{} + } + t.Log(issuer.State(t).String()) + valueArraySize := utils.GetValueArraySizeForOperator(operator) + + inputs := Inputs{ + RequestID: requestID, + UserGenesisID: user.ID.BigInt().String(), + ProfileNonce: nonce.String(), + UserAuthClaim: user.AuthClaim, + UserAuthClaimMtp: authMTProof, + UserAuthClaimNonRevMtp: userAuthNonRevMTProof, + UserAuthClaimNonRevMtpAuxHi: userNodeAuxNonRev.Key, + UserAuthClaimNonRevMtpAuxHv: userNodeAuxNonRev.Value, + UserAuthClaimNonRevMtpNoAux: userNodeAuxNonRev.NoAux, + Challenge: challenge.String(), + ChallengeSignatureR8X: sig.R8.X.String(), + ChallengeSignatureR8Y: sig.R8.Y.String(), + ChallengeSignatureS: sig.S.String(), + UserClaimsTreeRoot: user.Clt.Root().BigInt().String(), + UserRevTreeRoot: user.Ret.Root().BigInt().String(), + UserRootsTreeRoot: user.Rot.Root().BigInt().String(), + UserState: user.State(t).String(), + GistRoot: gistRoot.BigInt().String(), + GistMtp: gistProof, + GistMtpAuxHi: gistNodeAux.Key, + GistMtpAuxHv: gistNodeAux.Value, + GistMtpNoAux: gistNodeAux.NoAux, + ClaimSubjectProfileNonce: nonceSubject.String(), + IssuerID: issuer.ID.BigInt().String(), + IssuerClaim: claim, + IssuerClaimMtp: issuerClaimMtp, + IssuerClaimClaimsTreeRoot: issuerClaimClaimsTreeRoot, + IssuerClaimRevTreeRoot: issuerClaimRevTreeRoot, + IssuerClaimRootsTreeRoot: issuerClaimRootsTreeRoot, + IssuerClaimIdenState: issuerClaimIdenState, + IssuerClaimNonRevClaimsTreeRoot: issuer.Clt.Root(), + IssuerClaimNonRevRevTreeRoot: issuer.Ret.Root(), + IssuerClaimNonRevRootsTreeRoot: issuer.Rot.Root(), + IssuerClaimNonRevState: issuer.State(t).String(), + IssuerClaimNonRevMtp: issuerClaimNonRevMtp, + IssuerClaimNonRevMtpAuxHi: issuerClaimNonRevAux.Key, + IssuerClaimNonRevMtpAuxHv: issuerClaimNonRevAux.Value, + IssuerClaimNonRevMtpNoAux: issuerClaimNonRevAux.NoAux, + ClaimSchema: "267831521922558027206082390043321796944", + ClaimPathMtp: claimPathMtp, + ClaimPathMtpNoAux: claimPathMtpNoAux, + ClaimPathMtpAuxHi: claimPathMtpAuxHi, + ClaimPathMtpAuxHv: claimPathMtpAuxHv, + ClaimPathKey: claimPathKey, + ClaimPathValue: claimPathValue, + IsRevocationChecked: isRevocationChecked, + Operator: operator, + SlotIndex: slotIndex, + Timestamp: timestamp, + Value: valueInput, + ValueArraySize: valueArraySize, + IssuerClaimSignatureR8X: issuerClaimSignatureR8X, + IssuerClaimSignatureR8Y: issuerClaimSignatureR8Y, + IssuerClaimSignatureS: issuerClaimSignatureS, + IssuerAuthClaim: issuerAuthClaim, + IssuerAuthClaimMtp: issuerAuthClaimMtp, + IssuerAuthClaimNonRevMtp: issuerAuthClaimNonRevMtp, + IssuerAuthClaimNonRevMtpAuxHi: issuerAuthClaimNonRevMtpAuxHi, + IssuerAuthClaimNonRevMtpAuxHv: issuerAuthClaimNonRevMtpAuxHv, + IssuerAuthClaimNonRevMtpNoAux: issuerAuthClaimNonRevMtpNoAux, + IssuerAuthClaimsTreeRoot: issuerAuthClaimsTreeRoot, + IssuerAuthRevTreeRoot: issuerAuthRevTreeRoot, + IssuerAuthRootsTreeRoot: issuerAuthRootsTreeRoot, + IssuerAuthState: issuerAuthState, + + LinkNonce: linkNonce, + + ProofType: proofType, + + VerifierID: "21929109382993718606847853573861987353620810345503358891473103689157378049", + NullifierSessionID: nullifierSessionID, + IsBJJAuthEnabled: isBJJAuthEnabled, + } + + valuesHash, err := utils.PoseidonHashValue(utils.FromStringArrayToBigIntArray(inputs.Value)) + require.NoError(t, err) + claimSchemaInt, ok := big.NewInt(0).SetString(inputs.ClaimSchema, 10) + require.True(t, ok) + + linkID, err := utils.CalculateLinkID(linkNonce, claim) + require.NoError(t, err) + + operatorOutput := "0" + nullifier := "0" + verifierID, ok := big.NewInt(0).SetString(inputs.VerifierID, 10) + require.True(t, ok) + nullifierSessionID_, ok := big.NewInt(0).SetString(inputs.NullifierSessionID, 10) + require.True(t, ok) + if inputs.NullifierSessionID != "0" { + claimSchema, ok := big.NewInt(0).SetString(inputs.ClaimSchema, 10) + require.True(t, ok) + + nullifier, err = utils.CalculateNullify( + user.ID.BigInt(), + nonceSubject, + claimSchema, + verifierID, + nullifierSessionID_, + ) + require.NoError(t, err) + } + merklizedBigInt, ok := big.NewInt(0).SetString(merklized, 10) + + firstPartQueryHash, err := poseidon.Hash([]*big.Int{ + claimSchemaInt, + big.NewInt(int64(inputs.SlotIndex)), + big.NewInt(int64(inputs.Operator)), + pathKey, + merklizedBigInt, + valuesHash, + }) + require.NoError(t, err) + require.True(t, ok) + circuitQueryHash, err := poseidon.Hash([]*big.Int{ + firstPartQueryHash, + big.NewInt(int64(valueArraySize)), + big.NewInt(int64(isRevocationChecked)), + verifierID, + nullifierSessionID_, + new(big.Int), + }) + require.NoError(t, err) + + if operator == utils.SD { + operatorOutput = big.NewInt(10).String() + } + + var issuerState string + if proofType == "1" { + // sig + issuerState = issuerAuthState + } else { + // mtp + issuerState = issuerClaimIdenState + } + + out := Outputs{ + RequestID: requestID, + UserID: userProfileID.BigInt().String(), + IssuerID: issuer.ID.BigInt().String(), + IssuerClaimNonRevState: issuer.State(t).String(), + CircuitQueryHash: circuitQueryHash.String(), + Timestamp: timestamp, + Merklized: merklized, + Challenge: challenge.String(), + GistRoot: gistRoot.BigInt().String(), + ProofType: proofType, + IssuerState: issuerState, + LinkID: linkID, + OperatorOutput: operatorOutput, + Nullifier: nullifier, + IsBJJAuthEnabled: strconv.Itoa(isBJJAuthEnabled), + } + + jsonData, err := json.Marshal(TestData{ + desc, + inputs, + out, + }) + require.NoError(t, err) + + utils.SaveTestVector(t, fileName, string(jsonData)) +} + +type Inputs struct { + RequestID string `json:"requestID"` + + // user data + UserGenesisID string `json:"userGenesisID"` // + ProfileNonce string `json:"profileNonce"` // + ClaimSubjectProfileNonce string `json:"claimSubjectProfileNonce"` // + + UserAuthClaim *core.Claim `json:"authClaim"` + UserAuthClaimMtp []string `json:"authClaimIncMtp"` + UserAuthClaimNonRevMtp []string `json:"authClaimNonRevMtp"` + UserAuthClaimNonRevMtpAuxHi string `json:"authClaimNonRevMtpAuxHi"` + UserAuthClaimNonRevMtpAuxHv string `json:"authClaimNonRevMtpAuxHv"` + UserAuthClaimNonRevMtpNoAux string `json:"authClaimNonRevMtpNoAux"` + Challenge string `json:"challenge"` + ChallengeSignatureR8X string `json:"challengeSignatureR8x"` + ChallengeSignatureR8Y string `json:"challengeSignatureR8y"` + ChallengeSignatureS string `json:"challengeSignatureS"` + UserClaimsTreeRoot string `json:"userClaimsTreeRoot"` + UserRevTreeRoot string `json:"userRevTreeRoot"` + UserRootsTreeRoot string `json:"userRootsTreeRoot"` + UserState string `json:"userState"` + GistRoot string `json:"gistRoot"` + GistMtp []string `json:"gistMtp"` + GistMtpAuxHi string `json:"gistMtpAuxHi"` + GistMtpAuxHv string `json:"gistMtpAuxHv"` + GistMtpNoAux string `json:"gistMtpNoAux"` + + IssuerID string `json:"issuerID"` + // Claim + IssuerClaim *core.Claim `json:"issuerClaim"` + // Inclusion + IssuerClaimMtp []string `json:"issuerClaimMtp"` + IssuerClaimClaimsTreeRoot *merkletree.Hash `json:"issuerClaimClaimsTreeRoot"` + IssuerClaimRevTreeRoot *merkletree.Hash `json:"issuerClaimRevTreeRoot"` + IssuerClaimRootsTreeRoot *merkletree.Hash `json:"issuerClaimRootsTreeRoot"` + IssuerClaimIdenState string `json:"issuerClaimIdenState"` + + IsRevocationChecked int `json:"isRevocationChecked"` + IssuerClaimNonRevClaimsTreeRoot *merkletree.Hash `json:"issuerClaimNonRevClaimsTreeRoot"` + IssuerClaimNonRevRevTreeRoot *merkletree.Hash `json:"issuerClaimNonRevRevTreeRoot"` + IssuerClaimNonRevRootsTreeRoot *merkletree.Hash `json:"issuerClaimNonRevRootsTreeRoot"` + IssuerClaimNonRevState string `json:"issuerClaimNonRevState"` + IssuerClaimNonRevMtp []string `json:"issuerClaimNonRevMtp"` + IssuerClaimNonRevMtpAuxHi string `json:"issuerClaimNonRevMtpAuxHi"` + IssuerClaimNonRevMtpAuxHv string `json:"issuerClaimNonRevMtpAuxHv"` + IssuerClaimNonRevMtpNoAux string `json:"issuerClaimNonRevMtpNoAux"` + + ClaimSchema string `json:"claimSchema"` + + // Query + // JSON path + ClaimPathMtp []string `json:"claimPathMtp"` + ClaimPathMtpNoAux string `json:"claimPathMtpNoAux"` // 1 if aux node is empty, 0 if non-empty or for inclusion proofs + ClaimPathMtpAuxHi string `json:"claimPathMtpAuxHi"` // 0 for inclusion proof + ClaimPathMtpAuxHv string `json:"claimPathMtpAuxHv"` // 0 for inclusion proof + ClaimPathValue string `json:"claimPathValue"` // value in this path in merklized json-ld document + ClaimPathKey string `json:"claimPathKey"` // hash of path in merklized json-ld document + + Operator int `json:"operator"` + SlotIndex int `json:"slotIndex"` + Timestamp string `json:"timestamp"` + Value []string `json:"value"` + ValueArraySize int `json:"valueArraySize"` + + // additional sig inputs + IssuerClaimSignatureR8X string `json:"issuerClaimSignatureR8x"` + IssuerClaimSignatureR8Y string `json:"issuerClaimSignatureR8y"` + IssuerClaimSignatureS string `json:"issuerClaimSignatureS"` + IssuerAuthClaim *core.Claim `json:"issuerAuthClaim"` + IssuerAuthClaimMtp []string `json:"issuerAuthClaimMtp"` + IssuerAuthClaimNonRevMtp []string `json:"issuerAuthClaimNonRevMtp"` + IssuerAuthClaimNonRevMtpAuxHi string `json:"issuerAuthClaimNonRevMtpAuxHi"` + IssuerAuthClaimNonRevMtpAuxHv string `json:"issuerAuthClaimNonRevMtpAuxHv"` + IssuerAuthClaimNonRevMtpNoAux string `json:"issuerAuthClaimNonRevMtpNoAux"` + IssuerAuthClaimsTreeRoot string `json:"issuerAuthClaimsTreeRoot"` + IssuerAuthRevTreeRoot string `json:"issuerAuthRevTreeRoot"` + IssuerAuthRootsTreeRoot string `json:"issuerAuthRootsTreeRoot"` + IssuerAuthState string `json:"issuerAuthState"` + + ProofType string `json:"proofType"` // 1 for sig, 2 for mtp + + // Private random nonce, used to generate LinkID + LinkNonce string `json:"linkNonce"` + + VerifierID string `json:"verifierID"` + NullifierSessionID string `json:"nullifierSessionID"` + + IsBJJAuthEnabled int `json:"isBJJAuthEnabled"` +} + +type Outputs struct { + RequestID string `json:"requestID"` + UserID string `json:"userID"` + IssuerID string `json:"issuerID"` + IssuerClaimNonRevState string `json:"issuerClaimNonRevState"` + CircuitQueryHash string `json:"circuitQueryHash"` + GistRoot string `json:"gistRoot"` + Timestamp string `json:"timestamp"` + Merklized string `json:"merklized"` + ProofType string `json:"proofType"` // 1 for sig, 2 for mtp + Challenge string `json:"challenge"` + IssuerState string `json:"issuerState"` + LinkID string `json:"linkID"` + OperatorOutput string `json:"operatorOutput"` + Nullifier string `json:"nullifier"` + IsBJJAuthEnabled string `json:"isBJJAuthEnabled"` +} + +type TestData struct { + Desc string `json:"desc"` + In Inputs `json:"inputs"` + Out Outputs `json:"expOut"` +} diff --git a/testvectorgen/contract_data/v3_test.go b/testvectorgen/contract_data/v3/v3_test.go similarity index 96% rename from testvectorgen/contract_data/v3_test.go rename to testvectorgen/contract_data/v3/v3_test.go index 45b9d8b4..36d7afcb 100644 --- a/testvectorgen/contract_data/v3_test.go +++ b/testvectorgen/contract_data/v3/v3_test.go @@ -150,7 +150,7 @@ func generateStateTransitionData(t *testing.T, nextState bool, primaryPK, second // user authMTProof := primaryEntity.AuthMTPStrign(t) - authNonRevMTProof, nodeAuxNonRev := primaryEntity.ClaimRevMTP(t, primaryEntity.AuthClaim) + authNonRevMTProof, nodeAuxNonRev := primaryEntity.ClaimRevMTPLevels(t, primaryEntity.AuthClaim, utils.IdOwnershipLevels) oldState := primaryEntity.State(t) // old state is genesis oldCltRoot := primaryEntity.Clt.Root().BigInt().String() @@ -180,7 +180,7 @@ func generateStateTransitionData(t *testing.T, nextState bool, primaryPK, second oldRotRoot = primaryEntity.Rot.Root().BigInt().String() authMTProof = primaryEntity.AuthMTPStrign(t) - authNonRevMTProof, nodeAuxNonRev = primaryEntity.ClaimRevMTP(t, primaryEntity.AuthClaim) + authNonRevMTProof, nodeAuxNonRev = primaryEntity.ClaimRevMTPLevels(t, primaryEntity.AuthClaim, utils.IdOwnershipLevels) primaryEntityClaim := utils.DefaultUserClaim(t, primaryEntity.ID, nil) primaryEntity.AddClaim(t, primaryEntityClaim) } @@ -251,7 +251,7 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat const isRevoked = false const isSubjectIDProfile = true - valueInput := utils.PrepareStrArray([]string{"20010101"}, 64) + valueInput := utils.PrepareStrArray([]string{"20010101"}, utils.MaxValueArraySize) var user *utils.IdentityTest @@ -310,7 +310,7 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat } else { claim = utils.DefaultUserClaim(t, subjectID, nil) - claimPathMtp = utils.PrepareStrArray([]string{}, 32) + claimPathMtp = utils.PrepareStrArray([]string{}, utils.ClaimLevels) claimPathMtpNoAux = "0" claimPathMtpAuxHi = "0" claimPathMtpAuxHv = "0" @@ -353,13 +353,13 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat issuerAuthState = issuer.State(t).String() - issuerAuthClaimMtp, _ = issuer.ClaimMTP(t, issuer.AuthClaim) + issuerAuthClaimMtp, _ = issuer.ClaimMTPLevels(t, issuer.AuthClaim, utils.IssuerLevels) if !issuetGenesisState { issuer.AddClaim(t, claim) } - issuerClaimMtp, _ = issuer.ClaimMTP(t, claim) + issuerClaimMtp, _ = issuer.ClaimMTPLevels(t, claim, utils.IssuerLevels) require.NoError(t, err) issuerClaimIdenState = issuer.State(t).String() @@ -374,9 +374,9 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat } // prove revocation on latest state of the issuer - issuerClaimNonRevMtp, issuerClaimNonRevAux := issuer.ClaimRevMTP(t, claim) + issuerClaimNonRevMtp, issuerClaimNonRevAux := issuer.ClaimRevMTPLevels(t, claim, utils.IssuerLevels) - issuerAuthClaimNonRevMtp, issuerAuthClaimNodeAux := issuer.ClaimRevMTP(t, issuer.AuthClaim) + issuerAuthClaimNonRevMtp, issuerAuthClaimNodeAux := issuer.ClaimRevMTPLevels(t, issuer.AuthClaim, utils.IssuerLevels) issuerAuthClaimNonRevMtpNoAux = issuerAuthClaimNodeAux.NoAux issuerAuthClaimNonRevMtpAuxHi = issuerAuthClaimNodeAux.Key issuerAuthClaimNonRevMtpAuxHv = issuerAuthClaimNodeAux.Value @@ -402,7 +402,7 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat issuerAuthClaimNonRevMtpAuxHv = "0" issuerAuthClaimNonRevMtpNoAux = "0" - issuerAuthClaimMtp = utils.PrepareStrArray([]string{}, 40) + issuerAuthClaimMtp = utils.PrepareStrArray([]string{}, utils.IssuerLevels) issuerAuthClaim = &core.Claim{} @@ -416,7 +416,7 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat proofType = "2" } - gisTree, err := merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), 64) + gisTree, err := merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), utils.OnChainLevels) require.Nil(t, err) for _, data := range gistData { @@ -439,19 +439,19 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat // user if isBJJAuthEnabled == 1 { - authMTProof = user.AuthMTPStrign(t) - userAuthNonRevMTProof, userNodeAuxNonRev = user.ClaimRevMTP(t, user.AuthClaim) + authMTProof = user.AuthMTPStrignLevels(t, utils.IdOwnershipLevels) + userAuthNonRevMTProof, userNodeAuxNonRev = user.ClaimRevMTPLevels(t, user.AuthClaim, utils.IdOwnershipLevels) sig = user.Sign(challenge) gistProofRaw, _, err := gisTree.GenerateProof(context.Background(), user.IDHash(t), nil) require.NoError(t, err) gistRoot = gisTree.Root() - gistProof, gistNodeAux = utils.PrepareProof(gistProofRaw, utils.GistLevels) + gistProof, gistNodeAux = utils.PrepareProof(gistProofRaw, utils.OnChainLevels) } else { emptyArr := make([]*merkletree.Hash, 0) - authMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IdentityTreeLevels) - userAuthNonRevMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IdentityTreeLevels) + authMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IssuerLevels) + userAuthNonRevMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IssuerLevels) userNodeAuxNonRev = utils.NodeAuxValue{ Key: merkletree.HashZero.String(), Value: merkletree.HashZero.String(), @@ -466,7 +466,7 @@ func generateData(t *testing.T, desc string, gistData []*gistData, userFirstStat } gistRoot = &merkletree.HashZero - gistProof = utils.PrepareSiblingsStr(emptyArr, utils.GistLevels) + gistProof = utils.PrepareSiblingsStr(emptyArr, utils.OnChainLevels) gistNodeAux = utils.NodeAuxValue{ Key: merkletree.HashZero.String(), Value: merkletree.HashZero.String(), diff --git a/testvectorgen/credentials/onchain/v3/v3_test.go b/testvectorgen/credentials/onchain/v3/v3_test.go index cee317b5..ac5681b5 100644 --- a/testvectorgen/credentials/onchain/v3/v3_test.go +++ b/testvectorgen/credentials/onchain/v3/v3_test.go @@ -489,15 +489,15 @@ func generateTestDataWithOperatorAndRevCheck(t *testing.T, desc string, isUserID gistProofRaw, _, err := gisTree.GenerateProof(context.Background(), user.IDHash(t), nil) require.NoError(t, err) gistRoot = gisTree.Root() - gistProof, gistNodeAux = utils.PrepareProof(gistProofRaw, utils.GistLevels) + gistProof, gistNodeAux = utils.PrepareProof(gistProofRaw, utils.OnChainLevels) } else { emptyArr := make([]*merkletree.Hash, 0) addr := common.HexToAddress(ethAddress) challenge = new(big.Int).SetBytes(merkletree.SwapEndianness(addr.Bytes())) - authMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IdentityTreeLevels) - authNonRevMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IdentityTreeLevels) + authMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IssuerLevels) + authNonRevMTProof = utils.PrepareSiblingsStr(emptyArr, utils.IssuerLevels) user.AuthClaim, err = core.NewClaim(core.AuthSchemaHash) require.NoError(t, err) nodeAuxNonRev = utils.NodeAuxValue{ @@ -514,7 +514,7 @@ func generateTestDataWithOperatorAndRevCheck(t *testing.T, desc string, isUserID } gistRoot = &merkletree.HashZero - gistProof = utils.PrepareSiblingsStr(emptyArr, utils.GistLevels) + gistProof = utils.PrepareSiblingsStr(emptyArr, utils.OnChainLevels) gistNodeAux = utils.NodeAuxValue{ Key: merkletree.HashZero.String(), Value: merkletree.HashZero.String(), @@ -752,7 +752,7 @@ func generateJSONLD_NON_INCLUSION_TestData(t *testing.T, isUserIDProfile, isSubj require.NoError(t, err) gistRoot := gisTree.Root() - gistProof, gistNodAux := utils.PrepareProof(gistProofRaw, utils.GistLevels) + gistProof, gistNodAux := utils.PrepareProof(gistProofRaw, utils.OnChainLevels) valueArraySize := utils.GetValueArraySizeForOperator(utils.EXISTS) diff --git a/testvectorgen/utils/constants.go b/testvectorgen/utils/constants.go index baf35dfc..8728ddf5 100644 --- a/testvectorgen/utils/constants.go +++ b/testvectorgen/utils/constants.go @@ -87,7 +87,15 @@ const TestNormalClaimDocument = ` }}` const ( - IdentityTreeLevels = 40 - GistLevels = 64 - ClaimLevels = 32 + IssuerLevels = 40 + ClaimLevels = 32 + MaxValueArraySize = 64 + IdOwnershipLevels = 40 + OnChainLevels = 64 + + IssuerLevels2 = 16 + ClaimLevels2 = 16 + MaxValueArraySize2 = 64 + IdOwnershipLevels2 = 16 + OnChainLevels2 = 32 ) diff --git a/testvectorgen/utils/identity.go b/testvectorgen/utils/identity.go index 6bcf079b..3bb5f595 100644 --- a/testvectorgen/utils/identity.go +++ b/testvectorgen/utils/identity.go @@ -36,7 +36,12 @@ func (it *IdentityTest) State(t testing.TB) *big.Int { func (it *IdentityTest) AuthMTPStrign(t testing.TB) []string { p, _ := it.ClaimMTPRaw(t, it.AuthClaim) - return PrepareSiblingsStr(p.AllSiblings(), IdentityTreeLevels) + return PrepareSiblingsStr(p.AllSiblings(), IssuerLevels) +} + +func (it *IdentityTest) AuthMTPStrignLevels(t testing.TB, levels int) []string { + p, _ := it.ClaimMTPRaw(t, it.AuthClaim) + return PrepareSiblingsStr(p.AllSiblings(), levels) } func (it *IdentityTest) SignClaim(t testing.TB, claim *core.Claim) *babyjub.Signature { @@ -79,7 +84,22 @@ func (it *IdentityTest) ClaimMTP(t testing.TB, claim *core.Claim) (sibling []str t.Fatalf("can't generate proof %v", err) } - return PrepareProof(proof, IdentityTreeLevels) + return PrepareProof(proof, IssuerLevels) +} + +func (it *IdentityTest) ClaimMTPLevels(t testing.TB, claim *core.Claim, levels int) (sibling []string, nodeAux NodeAuxValue) { + // add auth claim to claimsMT + hi, _, err := claim.HiHv() + if err != nil { + t.Fatalf("can't get claim index hash %v", err) + } + + proof, _, err := it.Clt.GenerateProof(context.Background(), hi, nil) + if err != nil { + t.Fatalf("can't generate proof %v", err) + } + + return PrepareProof(proof, levels) } func (it *IdentityTest) ClaimRevMTPRaw(t testing.TB, claim *core.Claim) (*merkletree.Proof, *big.Int) { @@ -102,7 +122,20 @@ func (it *IdentityTest) ClaimRevMTP(t testing.TB, claim *core.Claim) (sibling [] t.Fatalf("can't generate proof %v", err) } - return PrepareProof(proof, IdentityTreeLevels) + return PrepareProof(proof, IssuerLevels) + +} + +func (it *IdentityTest) ClaimRevMTPLevels(t testing.TB, claim *core.Claim, levels int) (sibling []string, nodeAux NodeAuxValue) { + // add auth claim to claimsMT + revNonce := claim.GetRevocationNonce() + + proof, _, err := it.Ret.GenerateProof(context.Background(), new(big.Int).SetUint64(revNonce), nil) + if err != nil { + t.Fatalf("can't generate proof %v", err) + } + + return PrepareProof(proof, levels) } @@ -134,15 +167,15 @@ func NewIdentity(t testing.TB, privKHex string) *IdentityTest { // init claims tree - it.Clt, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IdentityTreeLevels) + it.Clt, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IssuerLevels) if err != nil { t.Fatalf("Error creating Claims merkle tree: %v", err) } - it.Ret, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IdentityTreeLevels) + it.Ret, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IssuerLevels) if err != nil { t.Fatalf("Error creating Revocation merkle tree: %v", err) } - it.Rot, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IdentityTreeLevels) + it.Rot, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IssuerLevels) if err != nil { t.Fatalf("Error creating Roots merkle tree: %v", err) } @@ -179,15 +212,15 @@ func NewEthereumBasedIdentity(t testing.TB, ethAddr string) *IdentityTest { // init claims tree - it.Clt, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IdentityTreeLevels) + it.Clt, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IssuerLevels) if err != nil { t.Fatalf("Error creating Claims merkle tree: %v", err) } - it.Ret, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IdentityTreeLevels) + it.Ret, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IssuerLevels) if err != nil { t.Fatalf("Error creating Revocation merkle tree: %v", err) } - it.Rot, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IdentityTreeLevels) + it.Rot, err = merkletree.NewMerkleTree(context.Background(), memory.NewMemoryStorage(), IssuerLevels) if err != nil { t.Fatalf("Error creating Roots merkle tree: %v", err) } diff --git a/update-contract-data-v3.js b/update-contract-data/update-contract-data-v3-stable-16-16-64-16-32.js similarity index 67% rename from update-contract-data-v3.js rename to update-contract-data/update-contract-data-v3-stable-16-16-64-16-32.js index ad8dc95b..ae6c85c9 100644 --- a/update-contract-data-v3.js +++ b/update-contract-data/update-contract-data-v3-stable-16-16-64-16-32.js @@ -1,9 +1,9 @@ -const dataFolder = './testvectorgen/contract_data/testdata/v3'; -const contractDataBaseFolder = '../contracts/test/validators/'; -const buildFolder = './build/'; const fs = require('fs'); const path = require('path'); -const { execSync, execFileSync } = require('child_process'); +const dataFolder = path.join(__dirname, '../testvectorgen/contract_data/v3-16-16-64-16-32/testdata/v3-16-16-64-16-32'); +const contractDataBaseFolder = path.join(__dirname, '../../contracts/test/validators/'); +const buildFolder = path.join(__dirname, '../build/'); +const { execSync } = require('child_process'); const files = fs.readdirSync(dataFolder); @@ -13,15 +13,14 @@ for (const file of files) { if (file.includes('state')) { - circuitName = 'stateTransition' - destinationFolder = 'common-data' + continue; } else { - circuitName = 'credentialAtomicQueryV3OnChain-beta.1' - destinationFolder = 'v3/data' + circuitName = 'credentialAtomicQueryV3OnChain-16-16-64-16-32'; + destinationFolder = 'v3-stable/data-16-16-64-16-32'; } - const buildPath = `./build/${circuitName}/${circuitName}_js/`; + const buildPath = `${buildFolder}${circuitName}/${circuitName}_js/`; ['input.json', 'public.json', 'proof.json'].forEach((f) => { - const p = path.join(`./build/${circuitName}/${circuitName}_js`, f) + const p = path.join(`${buildFolder}${circuitName}/${circuitName}_js`, f); fs.existsSync(p) && fs.unlinkSync(p); console.log(`Deleted file: ${p}`); diff --git a/update-contract-data/update-contract-data-v3-stable.js b/update-contract-data/update-contract-data-v3-stable.js new file mode 100644 index 00000000..a7208c61 --- /dev/null +++ b/update-contract-data/update-contract-data-v3-stable.js @@ -0,0 +1,45 @@ +const fs = require('fs'); +const path = require('path'); +const dataFolder = path.join(__dirname, '../testvectorgen/contract_data/v3/testdata/v3'); +const contractDataBaseFolder = path.join(__dirname, '../../contracts/test/validators/'); +const buildFolder = path.join(__dirname, '../build/'); +const { execSync } = require('child_process'); + +const files = fs.readdirSync(dataFolder); + +let circuitName = null; +let destinationFolder = null; +for (const file of files) { + if (file.includes('state')) { + circuitName = 'stateTransition'; + destinationFolder = 'common-data'; + } else { + circuitName = 'credentialAtomicQueryV3OnChain'; + destinationFolder = 'v3-stable/data'; + } + const buildPath = `${buildFolder}${circuitName}/${circuitName}_js/`; + ['input.json', 'public.json', 'proof.json'].forEach((f) => { + const p = path.join(`${buildFolder}${circuitName}/${circuitName}_js`, f); + fs.existsSync(p) && + fs.unlinkSync(p); + console.log(`Deleted file: ${p}`); + }); + const { inputs } = require(`${dataFolder}/${file}`); + console.log(`Reading file: ${dataFolder}/${file}`); + + console.log(`Creating file: ${buildPath}/input.json`); + fs.writeFileSync(`${buildPath}/input.json`, JSON.stringify(inputs), 'utf-8'); + const child = execSync(`./generate.sh ${circuitName}`); + console.log(`execution completed`, new TextDecoder().decode(child)); + const pub_signals = JSON.parse(fs.readFileSync(`${buildPath}/public.json`).toString()); + console.log(pub_signals); + const proof = JSON.parse(fs.readFileSync(`${buildPath}/proof.json`).toString()); + console.log('Writing file: ', `${contractDataBaseFolder}/${destinationFolder}/${file}`); + fs.writeFileSync(`${contractDataBaseFolder}/${destinationFolder}/${file}`, JSON.stringify({ + pub_signals, + proof + }), 'utf-8'); + +} + +console.log('Done'); diff --git a/update-contract-data/update-contract-data-v3.js b/update-contract-data/update-contract-data-v3.js new file mode 100644 index 00000000..10927f5a --- /dev/null +++ b/update-contract-data/update-contract-data-v3.js @@ -0,0 +1,45 @@ +const dataFolder = '../testvectorgen/contract_data/v3/testdata/v3'; +const contractDataBaseFolder = '../../contracts/test/validators/'; +const buildFolder = '../build/'; +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +const files = fs.readdirSync(dataFolder); + +let circuitName = null; +let destinationFolder = null; +for (const file of files) { + if (file.includes('state')) { + circuitName = 'stateTransition'; + destinationFolder = 'common-data'; + } else { + circuitName = 'credentialAtomicQueryV3OnChain-beta.1'; + destinationFolder = 'v3/data'; + } + const buildPath = `${buildFolder}${circuitName}/${circuitName}_js/`; + ['input.json', 'public.json', 'proof.json'].forEach((f) => { + const p = path.join(`${buildFolder}${circuitName}/${circuitName}_js`, f); + fs.existsSync(p) && + fs.unlinkSync(p); + console.log(`Deleted file: ${p}`); + }); + const { inputs } = require(`${dataFolder}/${file}`); + console.log(`Reading file: ${dataFolder}/${file}`); + + console.log(`Creating file: ${buildPath}/input.json`); + fs.writeFileSync(`${buildPath}/input.json`, JSON.stringify(inputs), 'utf-8'); + const child = execSync(`../generate.sh ${circuitName}`); + console.log(`execution completed`, new TextDecoder().decode(child)); + const pub_signals = JSON.parse(fs.readFileSync(`${buildPath}/public.json`).toString()); + console.log(pub_signals); + const proof = JSON.parse(fs.readFileSync(`${buildPath}/proof.json`).toString()); + console.log('Writing file: ', `${contractDataBaseFolder}/${destinationFolder}/${file}`); + fs.writeFileSync(`${contractDataBaseFolder}/${destinationFolder}/${file}`, JSON.stringify({ + pub_signals, + proof + }), 'utf-8'); + +} + +console.log('Done'); diff --git a/update-contract-data.js b/update-contract-data/update-contract-data.js similarity index 79% rename from update-contract-data.js rename to update-contract-data/update-contract-data.js index 099a5e55..1824859c 100644 --- a/update-contract-data.js +++ b/update-contract-data/update-contract-data.js @@ -1,9 +1,9 @@ -const dataFolder = './testvectorgen/contract_data/testdata/v3'; -const contractDataBaseFolder = '../contracts/test/validators/v'; -const buildFolder = './build/'; +const dataFolder = '../testvectorgen/contract_data/testdata/v3'; +const contractDataBaseFolder = '../../contracts/test/validators/v'; +const buildFolder = '../build/'; const fs = require('fs'); const path = require('path'); -const { execSync, execFileSync } = require('child_process'); +const { execSync } = require('child_process'); const files = fs.readdirSync(dataFolder); @@ -24,9 +24,9 @@ for (const file of files) { } else { throw new Error('unknown circuit') } - const buildPath = `./build/${circuitName}/${circuitName}_js/`; + const buildPath = `${buildFolder}${circuitName}/${circuitName}_js/`; ['input.json', 'public.json', 'proof.json'].forEach((f) => { - const p = path.join(`./build/${circuitName}/${circuitName}_js`, f) + const p = path.join(`${buildFolder}${circuitName}/${circuitName}_js`, f) fs.existsSync(p) && fs.unlinkSync(p); console.log(`Deleted file: ${p}`); @@ -36,7 +36,7 @@ for (const file of files) { console.log(`Creating file: ${buildPath}/input.json`); fs.writeFileSync(`${buildPath}/input.json`, JSON.stringify(inputs), 'utf-8'); - const child = execSync(`./generate.sh ${circuitName}`); + const child = execSync(`../generate.sh ${circuitName}`); console.log(`execution completed`, new TextDecoder().decode(child)); const pub_signals = JSON.parse(fs.readFileSync(`${buildPath}/public.json`).toString()); console.log(pub_signals); @@ -55,6 +55,6 @@ for (const part of ['MTP', 'Sig']) { const contractName = `${buildFolder}${circuitName}/verifier.sol`; const contractContent = fs.readFileSync(contractName).toString(); const newContractContent = contractContent.replace('pragma solidity ^0.6.11;', 'pragma solidity ^0.8.0;').replace('contract Verifier', 'contract Verifier' + part); - fs.writeFileSync(`../contracts/contracts/lib/verifier${part}.sol`, newContractContent, 'utf-8'); + fs.writeFileSync(`../../contracts/contracts/lib/verifier${part}.sol`, newContractContent, 'utf-8'); } console.log('Done');