feat: add automated production release workflow

This commit is contained in:
Prad Nukala
2024-09-23 12:25:15 -04:00
parent 05bda3d1b2
commit c31b324bd3
217 changed files with 19760 additions and 56358 deletions
+127 -22
View File
@@ -2,31 +2,67 @@ package keeper
import (
"context"
"crypto/sha256"
"fmt"
"time"
nftkeeper "cosmossdk.io/x/nft/keeper"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/onsonr/sonr/x/did/builder"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/client/rpc"
"github.com/ipfs/kubo/core/coreiface/options"
"github.com/onsonr/sonr/pkg/vault"
"github.com/onsonr/sonr/x/did/types"
"google.golang.org/grpc/peer"
"gopkg.in/macaroon.v2"
)
type Context struct {
SDKCtx sdk.Context
Keeper Keeper
Peer *peer.Peer
}
func (k Keeper) CurrentCtx(goCtx context.Context) Context {
func (k Keeper) UnwrapCtx(goCtx context.Context) Context {
ctx := sdk.UnwrapSDKContext(goCtx)
peer, _ := peer.FromContext(goCtx)
return Context{SDKCtx: ctx, Peer: peer, Keeper: k}
}
func (c Context) Params() *types.Params {
return c.Keeper.GetParams(c.SDK())
type Context struct {
SDKCtx sdk.Context
Keeper Keeper
Peer *peer.Peer
NFTKeeper nftkeeper.Keeper
}
func (c Context) SDK() sdk.Context {
return c.SDKCtx
// AssembleVault assembles the initial vault
func (k Keeper) AssembleVault(ctx Context, subject string, origin string) (string, int64, error) {
v, err := vault.New(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
}
// AverageBlockTime returns the average block time in seconds
func (c Context) AverageBlockTime() float64 {
return float64(c.SDK().BlockTime().Sub(c.SDK().BlockTime()).Seconds())
}
// 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())
}
// 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 {
@@ -36,6 +72,35 @@ func (c Context) IsAnonymous() bool {
return c.Peer.Addr == nil
}
// IssueMacaroon creates a macaroon with the specified parameters.
func (c Context) IssueMacaroon(sharedMPCPubKey, location, id string, blockExpiry uint64) (*macaroon.Macaroon, error) {
// Derive the root key by hashing the shared MPC public key
rootKey := sha256.Sum256([]byte(sharedMPCPubKey))
// Create the macaroon
m, err := macaroon.New(rootKey[:], []byte(id), location, macaroon.LatestVersion)
if err != nil {
return nil, err
}
// Add the block expiry caveat
caveat := fmt.Sprintf("block-expiry=%d", blockExpiry)
err = m.AddFirstPartyCaveat([]byte(caveat))
if err != nil {
return nil, err
}
return m, 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 &params
}
func (c Context) PeerID() string {
if c.Peer == nil {
return ""
@@ -43,18 +108,58 @@ func (c Context) PeerID() string {
return c.Peer.Addr.String()
}
func (c Context) GetService(origin string) (*types.Service, error) {
rec, err := c.Keeper.OrmDB.ServiceRecordTable().GetByOrigin(c.SDK(), origin)
// 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 nil, err
return false, err
}
return builder.ModuleFormatAPIServiceRecord(rec), nil
// 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
}
func (c Context) GetServiceInfo(origin string) *types.ServiceInfo {
rec, _ := c.GetService(origin)
if rec == nil {
return &types.ServiceInfo{Exists: false, Origin: origin, Fingerprint: types.ComputeOriginTXTRecord(origin)}
}
return &types.ServiceInfo{Exists: true, Origin: origin, Fingerprint: types.ComputeOriginTXTRecord(origin), Service: rec}
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()
}
+13 -16
View File
@@ -6,6 +6,7 @@ import (
"cosmossdk.io/log"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ipfs/boxo/path"
"github.com/onsonr/sonr/x/did/types"
)
@@ -21,7 +22,6 @@ func (k *Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) erro
if err := data.Params.Validate(); err != nil {
return err
}
return k.Params.Set(ctx, data.Params)
}
@@ -55,22 +55,19 @@ 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
}
v, err := k.ipfsClient.Unixfs().Get(ctx, path)
if err != nil {
return false, err
}
params := p.ActiveParams(k.HasIPFSConnection())
return &params
}
// 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))
if v == nil {
return false, nil
}
return true, nil
}
-38
View File
@@ -92,44 +92,6 @@ func NewKeeper(
return k
}
// IsClaimedServiceOrigin checks if a service origin is unclaimed
func (k Keeper) IsUnclaimedServiceOrigin(ctx sdk.Context, origin string) bool {
rec, _ := k.OrmDB.ServiceRecordTable().GetByOrigin(ctx, origin)
return rec == nil
}
// IsValidServiceOrigin checks if a service origin is valid
func (k Keeper) IsValidServiceOrigin(ctx sdk.Context, origin string) bool {
rec, err := k.OrmDB.ServiceRecordTable().GetByOrigin(ctx, origin)
if err != nil {
return false
}
if rec == nil {
return false
}
return true
}
// 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,
+7 -73
View File
@@ -21,87 +21,21 @@ 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.
func (k Querier) Resolve(
goCtx context.Context,
req *types.QueryRequest,
) (*types.QueryResponse, error) {
ctx := k.CurrentCtx(goCtx)
return &types.QueryResponse{Params: k.GetParams(ctx.SDK())}, nil
}
// Service implements types.QueryServer.
func (k Querier) Service(
goCtx context.Context,
req *types.QueryRequest,
) (*types.QueryResponse, error) {
ctx := k.CurrentCtx(goCtx)
return &types.QueryResponse{Service: ctx.GetServiceInfo(req.GetOrigin()), Params: ctx.Params()}, nil
}
// ParamsAssets implements types.QueryServer.
func (k Querier) ParamsAssets(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
panic("ParamsAssets is unimplemented")
return &types.QueryResponse{}, nil
}
// ParamsByAsset implements types.QueryServer.
func (k Querier) ParamsByAsset(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
panic("ParamsByAsset is unimplemented")
return &types.QueryResponse{}, nil
}
// ParamsKeys implements types.QueryServer.
func (k Querier) ParamsKeys(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
panic("ParamsKeys is unimplemented")
return &types.QueryResponse{}, nil
}
// ParamsByKey implements types.QueryServer.
func (k Querier) ParamsByKey(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
panic("ParamsByKey is unimplemented")
return &types.QueryResponse{}, nil
}
// RegistrationOptionsByKey implements types.QueryServer.
func (k Querier) RegistrationOptionsByKey(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
panic("RegistrationOptionsByKey is unimplemented")
return &types.QueryResponse{}, nil
// Accounts implements types.QueryServer.
func (k Querier) Accounts(goCtx context.Context, req *types.QueryAccountsRequest) (*types.QueryAccountsResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.QueryAccountsResponse{}, nil
}
// Credentials implements types.QueryServer.
func (k Querier) Credentials(goCtx context.Context, req *types.QueryCredentialsRequest) (*types.QueryCredentialsResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.QueryCredentialsResponse{}, nil
}
// Identities implements types.QueryServer.
func (k Querier) Identities(goCtx context.Context, req *types.QueryIdentitiesRequest) (*types.QueryIdentitiesResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.QueryIdentitiesResponse{}, nil
}
// Resolve implements types.QueryServer.
func (k Querier) Resolve(goCtx context.Context, req *types.QueryResolveRequest) (*types.QueryResolveResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
) (*types.QueryResolveResponse, error) {
_ = k.UnwrapCtx(goCtx)
return &types.QueryResolveResponse{}, nil
}
// Service implements types.QueryServer.
func (k Querier) Service(goCtx context.Context, req *types.QueryServiceRequest) (*types.QueryServiceResponse, error) {
// Sync implements types.QueryServer.
func (k Querier) Sync(goCtx context.Context, req *types.SyncRequest) (*types.SyncResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.QueryServiceResponse{}, nil
return &types.SyncResponse{}, nil
}
+27 -92
View File
@@ -11,12 +11,11 @@ import (
"github.com/onsonr/sonr/x/did/builder"
"github.com/onsonr/sonr/x/did/types"
"cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"cosmossdk.io/errors"
didv1 "github.com/onsonr/hway/api/did/v1"
"github.com/onsonr/hway/x/did/types"
"github.com/onsonr/sonr/x/did/types"
)
type msgServer struct {
@@ -30,21 +29,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.
@@ -52,32 +36,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
}
@@ -99,21 +73,28 @@ func (ms msgServer) RegisterService(
goCtx context.Context,
msg *types.MsgRegisterService,
) (*types.MsgRegisterServiceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// ctx := sdk.UnwrapSDKContext(goCtx)
// 1.Check if the service origin is valid
if !ms.k.IsValidServiceOrigin(ctx, msg.Service.Origin) {
return nil, types.ErrInvalidServiceOrigin
}
return ms.k.insertService(ctx, msg.Service)
// if !ms.k.IsValidServiceOrigin(ctx, msg.Service.Origin) {
// return nil, types.ErrInvalidServiceOrigin
// }
return nil, errors.Wrapf(types.ErrInvalidServiceOrigin, "invalid service origin")
}
// # SyncController
// # AuthorizeService
//
// SyncController implements types.MsgServer.
func (ms msgServer) SyncController(ctx context.Context, msg *types.MsgSyncController) (*types.MsgSyncControllerResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.MsgSyncControllerResponse{}, nil
// 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
@@ -133,49 +114,3 @@ func (ms msgServer) UpdateParams(
}
return nil, ms.k.Params.Set(ctx, msg.Params)
}
// Authenticate implements types.MsgServer.
func (ms msgServer) Authenticate(ctx context.Context, msg *types.MsgAuthenticate) (*types.MsgAuthenticateResponse, error) {
if ms.k.authority != msg.Authority {
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.k.authority, msg.Authority)
}
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.MsgAuthenticateResponse{}, nil
}
// RegisterController implements types.MsgServer.
func (ms msgServer) RegisterController(goCtx context.Context, msg *types.MsgRegisterController) (*types.MsgRegisterControllerResponse, error) {
if ms.k.authority != msg.Authority {
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.k.authority, msg.Authority)
}
return &types.MsgRegisterControllerResponse{}, nil
}
// RegisterService implements types.MsgServer.
func (ms msgServer) RegisterService(goCtx context.Context, msg *types.MsgRegisterService) (*types.MsgRegisterServiceResponse, error) {
if ms.k.authority != msg.Authority {
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.k.authority, msg.Authority)
}
ctx := sdk.UnwrapSDKContext(goCtx)
svc := didv1.Service{
ControllerDid: msg.Authority,
}
err := ms.k.OrmDB.ServiceTable().Insert(ctx, &svc)
if err != nil {
return nil, err
}
return &types.MsgRegisterServiceResponse{}, nil
}
// ProveWitness implements types.MsgServer.
func (ms msgServer) ProveWitness(ctx context.Context, msg *types.MsgProveWitness) (*types.MsgProveWitnessResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.MsgProveWitnessResponse{}, nil
}
// SyncVault implements types.MsgServer.
func (ms msgServer) SyncVault(ctx context.Context, msg *types.MsgSyncVault) (*types.MsgSyncVaultResponse, error) {
// ctx := sdk.UnwrapSDKContext(goCtx)
return &types.MsgSyncVaultResponse{}, nil
}