mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-05 10:51:41 +00:00
@@ -0,0 +1,363 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
apiv1 "github.com/sonr-io/sonr/api/did/v1"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
// GenesisOrmData holds all ORM table data for genesis import/export
|
||||
type GenesisOrmData struct {
|
||||
DidDocuments []*apiv1.DIDDocument
|
||||
Assertions []*apiv1.Assertion
|
||||
Controllers []*apiv1.Controller
|
||||
Authentications []*apiv1.Authentication
|
||||
DidMetadata []*apiv1.DIDDocumentMetadata
|
||||
Credentials []*apiv1.VerifiableCredential
|
||||
Delegations []*apiv1.Delegation
|
||||
Invocations []*apiv1.Invocation
|
||||
DidControllers []*apiv1.DIDController
|
||||
}
|
||||
|
||||
// InitGenesisWithORM initializes the module's state from genesis including all ORM tables
|
||||
// This function handles the ORM data separately from the base GenesisState
|
||||
func (k *Keeper) InitGenesisWithORM(ctx context.Context, data *types.GenesisState, ormData *GenesisOrmData) error {
|
||||
// Initialize params first
|
||||
if err := data.Params.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid params: %w", err)
|
||||
}
|
||||
|
||||
if err := k.Params.Set(ctx, data.Params); err != nil {
|
||||
return fmt.Errorf("failed to set params: %w", err)
|
||||
}
|
||||
|
||||
// If no ORM data provided, return early
|
||||
if ormData == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
||||
|
||||
// Import DID Documents
|
||||
if ormData.DidDocuments != nil {
|
||||
for _, doc := range ormData.DidDocuments {
|
||||
if err := k.OrmDB.DIDDocumentTable().Insert(ctx, doc); err != nil {
|
||||
sdkCtx.Logger().Error(
|
||||
"Failed to import DID document",
|
||||
"did", doc.Id,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import Assertions
|
||||
if ormData.Assertions != nil {
|
||||
for _, assertion := range ormData.Assertions {
|
||||
if err := k.OrmDB.AssertionTable().Insert(ctx, assertion); err != nil {
|
||||
sdkCtx.Logger().Error(
|
||||
"Failed to import assertion",
|
||||
"did", assertion.Did,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import Controllers
|
||||
if ormData.Controllers != nil {
|
||||
for _, controller := range ormData.Controllers {
|
||||
if err := k.OrmDB.ControllerTable().Insert(ctx, controller); err != nil {
|
||||
sdkCtx.Logger().Error(
|
||||
"Failed to import controller",
|
||||
"did", controller.Did,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import Authentications
|
||||
if ormData.Authentications != nil {
|
||||
for _, auth := range ormData.Authentications {
|
||||
if err := k.OrmDB.AuthenticationTable().Insert(ctx, auth); err != nil {
|
||||
sdkCtx.Logger().Error(
|
||||
"Failed to import authentication",
|
||||
"did", auth.Did,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import DID Document Metadata
|
||||
if ormData.DidMetadata != nil {
|
||||
for _, metadata := range ormData.DidMetadata {
|
||||
if err := k.OrmDB.DIDDocumentMetadataTable().Insert(ctx, metadata); err != nil {
|
||||
sdkCtx.Logger().Error(
|
||||
"Failed to import DID metadata",
|
||||
"did", metadata.Did,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import Verifiable Credentials
|
||||
if ormData.Credentials != nil {
|
||||
for _, cred := range ormData.Credentials {
|
||||
if err := k.OrmDB.VerifiableCredentialTable().Insert(ctx, cred); err != nil {
|
||||
sdkCtx.Logger().Error(
|
||||
"Failed to import credential",
|
||||
"id", cred.Id,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdkCtx.Logger().Info(
|
||||
"Genesis import completed",
|
||||
"did_documents", len(ormData.DidDocuments),
|
||||
"assertions", len(ormData.Assertions),
|
||||
"controllers", len(ormData.Controllers),
|
||||
"authentications", len(ormData.Authentications),
|
||||
"credentials", len(ormData.Credentials),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportGenesisWithORM exports the module's complete state to genesis
|
||||
func (k *Keeper) ExportGenesisWithORM(ctx context.Context) (*types.GenesisState, *GenesisOrmData, error) {
|
||||
params, err := k.Params.Get(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to get params: %w", err)
|
||||
}
|
||||
|
||||
genesis := &types.GenesisState{
|
||||
Params: params,
|
||||
}
|
||||
|
||||
ormData := &GenesisOrmData{}
|
||||
|
||||
// Export DID Documents
|
||||
didDocs, err := k.exportDIDDocuments(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to export DID documents: %w", err)
|
||||
}
|
||||
ormData.DidDocuments = didDocs
|
||||
|
||||
// Export Assertions
|
||||
assertions, err := k.exportAssertions(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to export assertions: %w", err)
|
||||
}
|
||||
ormData.Assertions = assertions
|
||||
|
||||
// Export Controllers
|
||||
controllers, err := k.exportControllers(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to export controllers: %w", err)
|
||||
}
|
||||
ormData.Controllers = controllers
|
||||
|
||||
// Export Authentications
|
||||
auths, err := k.exportAuthentications(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to export authentications: %w", err)
|
||||
}
|
||||
ormData.Authentications = auths
|
||||
|
||||
// Export DID Metadata
|
||||
metadata, err := k.exportDIDMetadata(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to export DID metadata: %w", err)
|
||||
}
|
||||
ormData.DidMetadata = metadata
|
||||
|
||||
// Export Verifiable Credentials
|
||||
creds, err := k.exportCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to export credentials: %w", err)
|
||||
}
|
||||
ormData.Credentials = creds
|
||||
|
||||
return genesis, ormData, nil
|
||||
}
|
||||
|
||||
// Helper functions for exporting each table
|
||||
|
||||
func (k *Keeper) exportDIDDocuments(ctx context.Context) ([]*apiv1.DIDDocument, error) {
|
||||
var documents []*apiv1.DIDDocument
|
||||
|
||||
iter, err := k.OrmDB.DIDDocumentTable().List(ctx, apiv1.DIDDocumentPrimaryKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
doc, err := iter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
documents = append(documents, doc)
|
||||
}
|
||||
|
||||
return documents, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) exportAssertions(ctx context.Context) ([]*apiv1.Assertion, error) {
|
||||
var assertions []*apiv1.Assertion
|
||||
|
||||
iter, err := k.OrmDB.AssertionTable().List(ctx, apiv1.AssertionPrimaryKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
assertion, err := iter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
assertions = append(assertions, assertion)
|
||||
}
|
||||
|
||||
return assertions, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) exportControllers(ctx context.Context) ([]*apiv1.Controller, error) {
|
||||
var controllers []*apiv1.Controller
|
||||
|
||||
iter, err := k.OrmDB.ControllerTable().List(ctx, apiv1.ControllerPrimaryKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
controller, err := iter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
controllers = append(controllers, controller)
|
||||
}
|
||||
|
||||
return controllers, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) exportAuthentications(ctx context.Context) ([]*apiv1.Authentication, error) {
|
||||
var auths []*apiv1.Authentication
|
||||
|
||||
iter, err := k.OrmDB.AuthenticationTable().List(ctx, apiv1.AuthenticationPrimaryKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
auth, err := iter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
auths = append(auths, auth)
|
||||
}
|
||||
|
||||
return auths, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) exportDIDMetadata(ctx context.Context) ([]*apiv1.DIDDocumentMetadata, error) {
|
||||
var metadata []*apiv1.DIDDocumentMetadata
|
||||
|
||||
iter, err := k.OrmDB.DIDDocumentMetadataTable().List(ctx, apiv1.DIDDocumentMetadataPrimaryKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
meta, err := iter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metadata = append(metadata, meta)
|
||||
}
|
||||
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) exportCredentials(ctx context.Context) ([]*apiv1.VerifiableCredential, error) {
|
||||
var credentials []*apiv1.VerifiableCredential
|
||||
|
||||
iter, err := k.OrmDB.VerifiableCredentialTable().List(ctx, apiv1.VerifiableCredentialPrimaryKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
cred, err := iter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credentials = append(credentials, cred)
|
||||
}
|
||||
|
||||
return credentials, nil
|
||||
}
|
||||
|
||||
// ValidateGenesisOrmData validates the ORM data for consistency
|
||||
func ValidateGenesisOrmData(ormData *GenesisOrmData) error {
|
||||
if ormData == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for duplicate DIDs
|
||||
didSet := make(map[string]bool)
|
||||
for _, doc := range ormData.DidDocuments {
|
||||
if didSet[doc.Id] {
|
||||
return fmt.Errorf("duplicate DID document: %s", doc.Id)
|
||||
}
|
||||
didSet[doc.Id] = true
|
||||
}
|
||||
|
||||
// Check for duplicate assertions (controller+subject must be unique)
|
||||
assertionSet := make(map[string]bool)
|
||||
for _, assertion := range ormData.Assertions {
|
||||
key := fmt.Sprintf("%s:%s", assertion.Controller, assertion.Subject)
|
||||
if assertionSet[key] {
|
||||
return fmt.Errorf("duplicate assertion for controller=%s, subject=%s",
|
||||
assertion.Controller, assertion.Subject)
|
||||
}
|
||||
assertionSet[key] = true
|
||||
}
|
||||
|
||||
// Check for duplicate controllers (address must be unique)
|
||||
addressSet := make(map[string]bool)
|
||||
for _, controller := range ormData.Controllers {
|
||||
if addressSet[controller.Address] {
|
||||
return fmt.Errorf("duplicate controller address: %s", controller.Address)
|
||||
}
|
||||
addressSet[controller.Address] = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isValidDerivedDID checks if a DID is a valid derived DID (email/tel)
|
||||
func isValidDerivedDID(did string) bool {
|
||||
// Check for email or tel DIDs
|
||||
if len(did) > 10 {
|
||||
prefix := did[:10]
|
||||
if prefix == "did:email:" || len(did) > 8 && did[:8] == "did:tel:" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user