Files
sonr/x/dwn/client/plugin/plugin.go
T
Prad NukalaandGitHub 13e6c3e84d Master (#1262)
* clear

* feat: Add everything

* fix: Commenht
2025-10-03 14:45:52 -04:00

204 lines
6.2 KiB
Go

// Package plugin provides a high-level interface for interacting with the Motor WebAssembly enclave plugin.
//
// The Motor plugin operates as an MPC-based UCAN (User-Controlled Authorization Networks)
// KeyshareSource, providing sophisticated decentralized authorization capabilities. This package abstracts the
// underlying WASM implementation and provides type-safe method calls for:
//
// - UCAN token creation and delegation
// - MPC-based cryptographic signing and verification
// - DID generation and identity management
// - Secure enclave configuration and management
//
// # Usage Example
//
// Basic usage with enclave configuration:
//
// ctx := context.Background()
// enclaveData, _ := json.Marshal(&mpc.EnclaveData{...})
// plugin, err := LoadPluginWithEnclave(ctx, "sonr-testnet-1", enclaveData, nil)
// if err != nil {
// log.Fatal(err)
// }
//
// // Create UCAN token
// req := &NewOriginTokenRequest{
// AudienceDID: "did:sonr:audience",
// Attenuations: []map[string]any{
// {"can": []string{"sign"}, "with": "vault://example"},
// },
// }
// resp, err := plugin.NewOriginToken(req)
package plugin
import (
"context"
"encoding/json"
"fmt"
extism "github.com/extism/go-sdk"
)
// Plugin defines the interface for cryptographic operations provided by the WebAssembly enclave.
// It abstracts the underlying WASM implementation and provides type-safe method calls.
// Updated to match the refactored MPC-based UCAN KeyshareSource Motor plugin.
type Plugin interface {
// UCAN Token Operations
// NewOriginToken creates a new UCAN origin token using MPC signing.
NewOriginToken(req *NewOriginTokenRequest) (*UCANTokenResponse, error)
// NewAttenuatedToken creates a delegated UCAN token with attenuated permissions.
NewAttenuatedToken(req *NewAttenuatedTokenRequest) (*UCANTokenResponse, error)
// Cryptographic Operations
// SignData signs arbitrary data using the MPC enclave.
SignData(req *SignDataRequest) (*SignDataResponse, error)
// VerifyData verifies a signature against data using the MPC enclave.
VerifyData(req *VerifyDataRequest) (*VerifyDataResponse, error)
// Identity Operations
// GetIssuerDID retrieves the issuer DID, address, and chain code from the enclave.
GetIssuerDID() (*GetIssuerDIDResponse, error)
}
// LoadPluginWithEnclave initializes and loads the WebAssembly MPC-based UCAN enclave plugin
// with the specified enclave configuration. This method provides basic enclave configuration
// but does not include advanced features like health monitoring and automatic recovery.
//
// For production use, consider LoadPluginWithManager which provides enhanced lifecycle management.
//
// Parameters:
// - ctx: Context for plugin initialization
// - chainID: Chain ID for the enclave (e.g., "sonr-testnet-1")
// - enclaveData: JSON-encoded MPC enclave data
// - vaultConfig: Optional vault configuration parameters
//
// Returns a Plugin interface for UCAN token operations and MPC cryptographic functions.
func LoadPluginWithEnclave(
ctx context.Context,
chainID string,
enclaveData []byte,
vaultConfig map[string]any,
) (Plugin, error) {
// Verify WASM integrity before loading
if err := VerifyPluginIntegrity(motrPluginBytes); err != nil {
return nil, fmt.Errorf("WASM integrity verification failed: %w", err)
}
manifest := GetManifestWithEnclave(chainID, enclaveData, vaultConfig)
cfg := GetPluginConfig()
plugin, err := extism.NewPlugin(ctx, manifest, cfg, []extism.HostFunction{})
if err != nil {
return nil, err
}
return &pluginImpl{plugin: plugin}, nil
}
// LoadPluginWithManager loads a Motor plugin using the enhanced plugin manager.
// This is the recommended method for production use as it provides:
// - Health monitoring and automatic recovery
// - Plugin instance caching and reuse
// - Comprehensive configuration validation
// - Background cleanup of expired instances
//
// Parameters:
// - ctx: Context for plugin initialization
// - config: Complete enclave configuration including timeouts, security settings, etc.
//
// Returns a managed Plugin interface with enhanced error handling and recovery.
func LoadPluginWithManager(ctx context.Context, config *EnclaveConfig) (Plugin, error) {
return DefaultManager.LoadPlugin(ctx, config)
}
type pluginImpl struct {
plugin *extism.Plugin
}
// UCAN Token Operations - Primary interface for the refactored Motor plugin
func (p *pluginImpl) NewOriginToken(req *NewOriginTokenRequest) (*UCANTokenResponse, error) {
reqBytes, err := json.Marshal(req)
if err != nil {
return nil, err
}
_, r, err := p.plugin.Call("new_origin_token", reqBytes)
if err != nil {
return nil, err
}
var resp UCANTokenResponse
if err := json.Unmarshal(r, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// NewAttenuatedToken creates an attenuated UCAN token by delegating from a parent token.
func (p *pluginImpl) NewAttenuatedToken(
req *NewAttenuatedTokenRequest,
) (*UCANTokenResponse, error) {
reqBytes, err := json.Marshal(req)
if err != nil {
return nil, err
}
_, r, err := p.plugin.Call("new_attenuated_token", reqBytes)
if err != nil {
return nil, err
}
var resp UCANTokenResponse
if err := json.Unmarshal(r, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// Cryptographic Operations
func (p *pluginImpl) SignData(req *SignDataRequest) (*SignDataResponse, error) {
reqBytes, err := json.Marshal(req)
if err != nil {
return nil, err
}
_, r, err := p.plugin.Call("sign_data", reqBytes)
if err != nil {
return nil, err
}
var resp SignDataResponse
if err := json.Unmarshal(r, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (p *pluginImpl) VerifyData(req *VerifyDataRequest) (*VerifyDataResponse, error) {
reqBytes, err := json.Marshal(req)
if err != nil {
return nil, err
}
_, r, err := p.plugin.Call("verify_data", reqBytes)
if err != nil {
return nil, err
}
var resp VerifyDataResponse
if err := json.Unmarshal(r, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// Identity Operations
func (p *pluginImpl) GetIssuerDID() (*GetIssuerDIDResponse, error) {
_, r, err := p.plugin.Call("get_issuer_did", []byte{})
if err != nil {
return nil, err
}
var resp GetIssuerDIDResponse
if err := json.Unmarshal(r, &resp); err != nil {
return nil, err
}
return &resp, nil
}