mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-04 02:11:40 +00:00
feature/migrate models (#16)
* feat: add new supported attestation formats to genesis * feat: refactor keyType to keytype enum * refactor: remove unused imports and code * refactor: update main.go to use src package * refactor: move web-related structs from to * refactor: move client middleware package to root * refactor: remove unused IndexedDB dependency * feat: update worker implementation to use * feat: add Caddyfile and Caddy configuration for vault service * refactor(config): move keyshare and address to Motr config * fix: validate service origin in AllocateVault * chore: remove IndexedDB configuration * feat: add support for IPNS-based vault access
This commit is contained in:
+60
-9
@@ -1,7 +1,9 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
@@ -14,18 +16,26 @@ type Context struct {
|
||||
Peer *peer.Peer
|
||||
}
|
||||
|
||||
func (k Keeper) CurrentCtx(goCtx context.Context) Context {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
peer, _ := peer.FromContext(goCtx)
|
||||
return Context{SDKCtx: ctx, Peer: peer, Keeper: k}
|
||||
// AverageBlockTime returns the average block time in seconds
|
||||
func (c Context) AverageBlockTime() float64 {
|
||||
return float64(c.SDK().BlockTime().Sub(c.SDK().BlockTime()).Seconds())
|
||||
}
|
||||
|
||||
func (c Context) Params() *types.Params {
|
||||
return c.Keeper.GetParams(c.SDK())
|
||||
// GetExpirationBlockHeight returns the block height at which the given duration will have passed
|
||||
func (c Context) CalculateExpiration(duration time.Duration) int64 {
|
||||
return c.SDKCtx.BlockHeight() + int64(duration.Seconds()/c.AverageBlockTime())
|
||||
}
|
||||
|
||||
func (c Context) SDK() sdk.Context {
|
||||
return c.SDKCtx
|
||||
// IPFSConnected returns true if the IPFS client is initialized
|
||||
func (c Context) IPFSConnected() bool {
|
||||
if c.Keeper.ipfsClient == nil {
|
||||
ipfsClient, err := rpc.NewLocalApi()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
c.Keeper.ipfsClient = ipfsClient
|
||||
}
|
||||
return c.Keeper.ipfsClient != nil
|
||||
}
|
||||
|
||||
func (c Context) IsAnonymous() bool {
|
||||
@@ -35,9 +45,50 @@ func (c Context) IsAnonymous() bool {
|
||||
return c.Peer.Addr == nil
|
||||
}
|
||||
|
||||
func (c Context) Params() *types.Params {
|
||||
p, err := c.Keeper.Params.Get(c.SDK())
|
||||
if err != nil {
|
||||
p = types.DefaultParams()
|
||||
}
|
||||
params := p.ActiveParams(c.IPFSConnected())
|
||||
return ¶ms
|
||||
}
|
||||
|
||||
func (c Context) PeerID() string {
|
||||
if c.Peer == nil {
|
||||
return ""
|
||||
}
|
||||
return c.Peer.Addr.String()
|
||||
}
|
||||
|
||||
func (c Context) SDK() sdk.Context {
|
||||
return c.SDKCtx
|
||||
}
|
||||
|
||||
// ValidateOrigin checks if a service origin is valid
|
||||
func (c Context) ValidateOrigin(origin string) error {
|
||||
if origin == "localhost" {
|
||||
return nil
|
||||
}
|
||||
return types.ErrInvalidServiceOrigin
|
||||
}
|
||||
|
||||
// VerifyMinimumStake checks if a validator has a minimum stake
|
||||
func (c Context) VerifyMinimumStake(addr string) bool {
|
||||
address, err := sdk.AccAddressFromBech32(addr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
addval, err := sdk.ValAddressFromBech32(addr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
del, err := c.Keeper.StakingKeeper.GetDelegation(c.SDK(), address, addval)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if del.Shares.IsZero() {
|
||||
return false
|
||||
}
|
||||
return del.Shares.IsPositive()
|
||||
}
|
||||
|
||||
+19
-15
@@ -2,10 +2,11 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
@@ -54,22 +55,25 @@ func (k Keeper) CheckValidatorExists(ctx sdk.Context, addr string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// GetAverageBlockTime returns the average block time in seconds
|
||||
func (k Keeper) GetAverageBlockTime(ctx sdk.Context) float64 {
|
||||
return float64(ctx.BlockTime().Sub(ctx.BlockTime()).Seconds())
|
||||
}
|
||||
|
||||
// GetParams returns the module parameters.
|
||||
func (k Keeper) GetParams(ctx sdk.Context) *types.Params {
|
||||
p, err := k.Params.Get(ctx)
|
||||
// HasPathInIPFS checks if a file is in the local IPFS node
|
||||
func (k Keeper) HasPathInIPFS(ctx sdk.Context, cid string) (bool, error) {
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
p = types.DefaultParams()
|
||||
return false, err
|
||||
}
|
||||
params := p.ActiveParams(k.HasIPFSConnection())
|
||||
return ¶ms
|
||||
v, err := k.ipfsClient.Unixfs().Get(ctx, path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// GetExpirationBlockHeight returns the block height at which the given duration will have passed
|
||||
func (k Keeper) GetExpirationBlockHeight(ctx sdk.Context, duration time.Duration) int64 {
|
||||
return ctx.BlockHeight() + int64(duration.Seconds()/k.GetAverageBlockTime(ctx))
|
||||
func (k Keeper) UnwrapCtx(goCtx context.Context) Context {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
peer, _ := peer.FromContext(goCtx)
|
||||
return Context{SDKCtx: ctx, Peer: peer, Keeper: k}
|
||||
}
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
"github.com/ipfs/kubo/core/coreiface/options"
|
||||
"github.com/onsonr/sonr/internal/vfs"
|
||||
)
|
||||
|
||||
// assembleInitialVault assembles the initial vault
|
||||
func (k Keeper) assembleInitialVault(ctx sdk.Context) (string, int64, error) {
|
||||
cnfg, err := vfs.NewDWNConfigFile("test", "test")
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
fileMap := map[string]files.Node{
|
||||
"config.pkl": cnfg,
|
||||
"sw.js": vfs.SWJSFile(),
|
||||
"app.wasm": vfs.DWNWasmFile(),
|
||||
"index.html": vfs.IndexFile(),
|
||||
}
|
||||
|
||||
cid, err := k.ipfsClient.Unixfs().Add(context.Background(), files.NewMapDirectory(fileMap))
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
return cid.String(), k.GetExpirationBlockHeight(ctx, time.Second*15), nil
|
||||
}
|
||||
|
||||
// pinInitialVault pins the initial vault to the local IPFS node
|
||||
func (k Keeper) pinInitialVault(_ sdk.Context, cid string, address string) (bool, error) {
|
||||
// Resolve the path
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 1. Initialize vault.db sqlite database in local IPFS with Mount
|
||||
|
||||
// 2. Insert the InitialWalletAccounts
|
||||
|
||||
// 3. Publish the path to the IPNS
|
||||
_, err = k.ipfsClient.Name().Publish(context.Background(), path, options.Name.Key(address))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 4. Insert the accounts into x/auth
|
||||
|
||||
// 5. Insert the controller into state
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// GetFromIPFS gets a file from the local IPFS node
|
||||
func (k Keeper) GetFromIPFS(ctx sdk.Context, cid string) (files.Directory, error) {
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := k.ipfsClient.Unixfs().Get(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dir, ok := node.(files.Directory)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("retrieved node is not a directory")
|
||||
}
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
// HasIPFSConnection returns true if the IPFS client is initialized
|
||||
func (k *Keeper) HasIPFSConnection() bool {
|
||||
if k.ipfsClient == nil {
|
||||
ipfsClient, err := rpc.NewLocalApi()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
k.ipfsClient = ipfsClient
|
||||
}
|
||||
return k.ipfsClient != nil
|
||||
}
|
||||
|
||||
// HasPathInIPFS checks if a file is in the local IPFS node
|
||||
func (k Keeper) HasPathInIPFS(ctx sdk.Context, cid string) (bool, error) {
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := k.ipfsClient.Unixfs().Get(ctx, path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// PinToIPFS pins a file to the local IPFS node
|
||||
func (k Keeper) PinToIPFS(ctx sdk.Context, cid string, name string) error {
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = k.ipfsClient.Pin().Add(ctx, path, options.Pin.Name(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -92,26 +92,6 @@ func NewKeeper(
|
||||
return k
|
||||
}
|
||||
|
||||
// VerifyMinimumStake checks if a validator has a minimum stake
|
||||
func (k Keeper) VerifyMinimumStake(ctx sdk.Context, addr string) bool {
|
||||
address, err := sdk.AccAddressFromBech32(addr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
addval, err := sdk.ValAddressFromBech32(addr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
del, err := k.StakingKeeper.GetDelegation(ctx, address, addval)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if del.Shares.IsZero() {
|
||||
return false
|
||||
}
|
||||
return del.Shares.IsPositive()
|
||||
}
|
||||
|
||||
// VerifyServicePermissions checks if a service has permission
|
||||
func (k Keeper) VerifyServicePermissions(
|
||||
ctx sdk.Context,
|
||||
|
||||
+3
-13
@@ -21,8 +21,8 @@ func (k Querier) Params(
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryParamsResponse, error) {
|
||||
ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryParamsResponse{Params: k.GetParams(ctx.SDK())}, nil
|
||||
ctx := k.UnwrapCtx(goCtx)
|
||||
return &types.QueryParamsResponse{Params: ctx.Params()}, nil
|
||||
}
|
||||
|
||||
// Resolve implements types.QueryServer.
|
||||
@@ -30,22 +30,12 @@ func (k Querier) Resolve(
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryResolveResponse, error) {
|
||||
_ = k.CurrentCtx(goCtx)
|
||||
_ = k.UnwrapCtx(goCtx)
|
||||
return &types.QueryResolveResponse{}, nil
|
||||
}
|
||||
|
||||
// Service implements types.QueryServer.
|
||||
func (k Querier) Service(
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryServiceResponse, error) {
|
||||
// ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryServiceResponse{}, nil
|
||||
}
|
||||
|
||||
// Sync implements types.QueryServer.
|
||||
func (k Querier) Sync(goCtx context.Context, req *types.SyncRequest) (*types.SyncResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
panic("Sync is unimplemented")
|
||||
return &types.SyncResponse{}, nil
|
||||
}
|
||||
|
||||
+24
-36
@@ -2,13 +2,11 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/builder"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@@ -23,21 +21,6 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
|
||||
return &msgServer{k: keeper}
|
||||
}
|
||||
|
||||
// # AuthorizeService
|
||||
//
|
||||
// AuthorizeService implements types.MsgServer.
|
||||
func (ms msgServer) AuthorizeService(goCtx context.Context, msg *types.MsgAuthorizeService) (*types.MsgAuthorizeServiceResponse, error) {
|
||||
if ms.k.authority != msg.Controller {
|
||||
return nil, errors.Wrapf(
|
||||
govtypes.ErrInvalidSigner,
|
||||
"invalid authority; expected %s, got %s",
|
||||
ms.k.authority,
|
||||
msg.Controller,
|
||||
)
|
||||
}
|
||||
return &types.MsgAuthorizeServiceResponse{}, nil
|
||||
}
|
||||
|
||||
// # AllocateVault
|
||||
//
|
||||
// AllocateVault implements types.MsgServer.
|
||||
@@ -45,32 +28,22 @@ func (ms msgServer) AllocateVault(
|
||||
goCtx context.Context,
|
||||
msg *types.MsgAllocateVault,
|
||||
) (*types.MsgAllocateVaultResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// 1.Check if the service origin is valid
|
||||
// if ms.k.IsValidServiceOrigin(ctx, msg.Origin) {
|
||||
// return nil, types.ErrInvalidServiceOrigin
|
||||
// }
|
||||
ctx := ms.k.UnwrapCtx(goCtx)
|
||||
if err := ctx.ValidateOrigin(msg.Origin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cid, expiryBlock, err := ms.k.assembleInitialVault(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
regOpts, err := builder.GetPublicKeyCredentialCreationOptions(msg.Origin, msg.Subject, cid, ms.k.GetParams(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert to string
|
||||
regOptsJSON, err := json.Marshal(regOpts)
|
||||
// 2.Allocate the vault
|
||||
cid, expiryBlock, err := ms.k.AssembleVault(ctx, msg.GetSubject(), msg.GetOrigin())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3.Return the response
|
||||
return &types.MsgAllocateVaultResponse{
|
||||
ExpiryBlock: expiryBlock,
|
||||
Cid: cid,
|
||||
RegistrationOptions: string(regOptsJSON),
|
||||
ExpiryBlock: expiryBlock,
|
||||
Cid: cid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -101,6 +74,21 @@ func (ms msgServer) RegisterService(
|
||||
return nil, errors.Wrapf(types.ErrInvalidServiceOrigin, "invalid service origin")
|
||||
}
|
||||
|
||||
// # AuthorizeService
|
||||
//
|
||||
// AuthorizeService implements types.MsgServer.
|
||||
func (ms msgServer) AuthorizeService(goCtx context.Context, msg *types.MsgAuthorizeService) (*types.MsgAuthorizeServiceResponse, error) {
|
||||
if ms.k.authority != msg.Controller {
|
||||
return nil, errors.Wrapf(
|
||||
govtypes.ErrInvalidSigner,
|
||||
"invalid authority; expected %s, got %s",
|
||||
ms.k.authority,
|
||||
msg.Controller,
|
||||
)
|
||||
}
|
||||
return &types.MsgAuthorizeServiceResponse{}, nil
|
||||
}
|
||||
|
||||
// # UpdateParams
|
||||
//
|
||||
// UpdateParams updates the x/did module parameters.
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/ipfs/kubo/core/coreiface/options"
|
||||
"github.com/onsonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/internal/vfs"
|
||||
)
|
||||
|
||||
type Vault struct {
|
||||
FS files.Node
|
||||
ValKs mpc.Share
|
||||
}
|
||||
|
||||
func NewVault(subject string, origin string, chainID string) (*Vault, error) {
|
||||
shares, err := mpc.GenerateKeyshares()
|
||||
var (
|
||||
valKs = shares[0]
|
||||
usrKs = shares[1]
|
||||
)
|
||||
usrKsJSON, err := usrKs.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sonrAddr, err := bech32.ConvertAndEncode("idx", valKs.GetPublicKey())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cnfg, err := vfs.NewDWNConfigFile(usrKsJSON, sonrAddr, chainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileMap := map[string]files.Node{
|
||||
"config.json": cnfg,
|
||||
"sw.js": vfs.SWJSFile(),
|
||||
"app.wasm": vfs.DWNWasmFile(),
|
||||
"index.html": vfs.IndexFile(),
|
||||
}
|
||||
return &Vault{
|
||||
FS: files.NewMapDirectory(fileMap),
|
||||
ValKs: valKs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AssembleVault assembles the initial vault
|
||||
func (k Keeper) AssembleVault(ctx Context, subject string, origin string) (string, int64, error) {
|
||||
v, err := NewVault(subject, origin, "sonr-testnet")
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
cid, err := k.ipfsClient.Unixfs().Add(context.Background(), v.FS)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
return cid.String(), ctx.CalculateExpiration(time.Second * 15), nil
|
||||
}
|
||||
|
||||
// PinVaultController pins the initial vault to the local IPFS node
|
||||
func (k Keeper) PinVaultController(_ sdk.Context, cid string, address string) (bool, error) {
|
||||
// Resolve the path
|
||||
path, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 1. Initialize vault.db sqlite database in local IPFS with Mount
|
||||
|
||||
// 2. Insert the InitialWalletAccounts
|
||||
|
||||
// 3. Publish the path to the IPNS
|
||||
_, err = k.ipfsClient.Name().Publish(context.Background(), path, options.Name.Key(address))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 4. Insert the accounts into x/auth
|
||||
|
||||
// 5. Insert the controller into state
|
||||
return true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user