Add Claim to the Claims Tree
At t=0, the situation is the same left from the Identity section of tutorial. Our identity is still at the Genesis State
. The Claims Tree contains only the authClaim
. The revocation and roots trees are empty. The state hasn't been published on-chain yet.
Let's see what happens when if we decide to add a new claim to the Claims Tree.
1.Update the required dependencies.
go get github.com/iden3/go-circuits
2.Add a new claim and fetch the new state
package main
import (
"encoding/hex"
"fmt"
"math/big"
"github.com/iden3/go-circuits"
core "github.com/iden3/go-iden3-core"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/iden3/go-merkletree-sql"
)
// Change Identity State
func main() {
// GENESIS STATE:
// 1. Generate Merkle Tree Proof for authClaim at Genesis State
authMTPProof, _, _ := clt.GenerateProof(ctx, hIndex, clt.Root())
// 2. Generate the Non-Revocation Merkle tree proof for the authClaim at Genesis State
authNonRevMTPProof, _, _ := ret.GenerateProof(ctx, new(big.Int).SetUint64(revNonce), ret.Root())
// Snapshot of the Genesis State
genesisTreeState := circuits.TreeState{
State: state,
ClaimsRoot: clt.Root(),
RevocationRoot: ret.Root(),
RootOfRoots: rot.Root(),
}
// STATE 1:
// Before updating the claims tree, add the claims tree root at Genesis state to the Roots tree.
rot.Add(ctx, clt.Root().BigInt(), big.NewInt(0))
// Create a new random claim
schemaHex := hex.EncodeToString([]byte("myAge_test_claim"))
schema, _ := core.NewSchemaHashFromHex(schemaHex)
code := big.NewInt(51)
newClaim, _ := core.NewClaim(schema, core.WithIndexDataInts(code, nil))
// Get hash Index and hash Value of the new claim
hi, hv, _ := newClaim.HiHv()
// Add claim to the Claims tree
clt.Add(ctx, hi, hv)
// Fetch the new Identity State
newState, _ := merkletree.HashElems(
clt.Root().BigInt(),
ret.Root().BigInt(),
rot.Root().BigInt())
// Snapshot of the new tree State
newTreeState := circuits.TreeState{
State: newState,
ClaimsRoot: clt.Root(),
RevocationRoot: ret.Root(),
RootOfRoots: rot.Root(),
}
// Sign a message (hash of the genesis state + the new state) using your private key
hashOldAndNewStates, _ := poseidon.Hash([]*big.Int{state.BigInt(), newState.BigInt()})
signature := babyJubjubPrivKey.SignPoseidon(hashOldAndNewStates)
authClaimNewStateIncMtp, _, _ := clt.GenerateProof(ctx, hIndex, newTreeState.ClaimsRoot)
// Generate state transition inputs
stateTransitionInputs := circuits.StateTransitionInputs{
ID: id,
OldTreeState: genesisTreeState,
NewTreeState: newTreeState,
IsOldStateGenesis: true,
AuthClaim: authClaim,
AuthClaimIncMtp: authMTPProof,
AuthClaimNonRevMtp: authNonRevMTPProof,
AuthClaimNewStateIncMtp: authClaimNewStateIncMtp,
Signature: signature,
}
// Perform marshalling of the state transition inputs
inputBytes, _ := stateTransitionInputs.InputsMarshal()
fmt.Println(string(inputBytes))
}
After issuing a new claim, the claims tree gets modified and, therefore, the Identity State changes. To complete the state transition it is necessary to verify it inside a circuit. The type StateTransitionInputs
lets us pack the inputs needed to generate a proof while the InputsMarshal()
function turns it into a json file that can be used directly as State Transition Circuit inputs. These inputs will be used in the next section.
The executable code can be found here