Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HID-Dev v0.0.1 #35

Closed
2 of 3 tasks
Vishwas1 opened this issue Jan 19, 2022 · 7 comments
Closed
2 of 3 tasks

HID-Dev v0.0.1 #35

Vishwas1 opened this issue Jan 19, 2022 · 7 comments
Assignees

Comments

@Vishwas1
Copy link
Contributor

Vishwas1 commented Jan 19, 2022

Requirement

  • We will have understanding of EVMOS ecosystem
  • We will have an understanding of how to add custom modules in comosSDK after exploring starport.
  • We will add a custom module (decentralised version of our core) in EVMOS code base to do the following:
  • We will send/receive DID using IBC from the EVMOS network to others.
  • Now that core (or our network) is ready , we can use our hs-ssi-sdk to interact with core for did, vc etc.
  • Now that our hs-ssi-sdk is connected with our own network, we can test our existing products like hypersign-auth , hyperfyre etc on this framework.
  • Release of DevNet This would help us understand how arbitrary data can be sent and received via IBC.

Tasks

  • Scaffold a new blockchain. Name it HID-core
  • We can go ahead in implementing a simple did module using startport cli on HID-dev the way they have scaffolded blog module in their doc. Use this schema
  • Now, do the above step in EVMOS code base as well.
@Vishwas1 Vishwas1 changed the title HIN-Dev HIN-Dev v0.0.1 Jan 19, 2022
@Vishwas1 Vishwas1 changed the title HIN-Dev v0.0.1 HID-Dev v0.0.1 Jan 20, 2022
@arnabghose997
Copy link

arnabghose997 commented Jan 22, 2022

Scaffolding a new blockchain

Starport Installation Guide: https://docs.starport.com/guide/install.html

To scaffold the hid-node, run the following:

$ starport scaffold chain hid-node

To scaffold the hid-node without any module, run the following:

$ starport scaffold chain hid-node --no-module

@arnabghose997
Copy link

arnabghose997 commented Jan 22, 2022

Building the DID module

PR Reference: hypersign-protocol/hid-node#2

  • Run the command to create the DID module x/did:
$ starport scaffold module did

modify app/app.go
create proto/did/genesis.proto
create proto/did/params.proto
create proto/did/query.proto
create proto/did/tx.proto
create testutil/keeper/did.go
create x/did/client/cli/query.go
create x/did/client/cli/query_params.go
create x/did/client/cli/tx.go
create x/did/genesis.go
create x/did/genesis_test.go
create x/did/handler.go
create x/did/keeper/grpc_query.go
create x/did/keeper/grpc_query_params.go
create x/did/keeper/grpc_query_params_test.go
create x/did/keeper/keeper.go
create x/did/keeper/msg_server.go
create x/did/keeper/msg_server_test.go
create x/did/keeper/params.go
create x/did/keeper/params_test.go
create x/did/module.go
create x/did/module_simulation.go
create x/did/simulation/simap.go
create x/did/types/codec.go
create x/did/types/errors.go
create x/did/types/expected_keepers.go
create x/did/types/genesis.go
create x/did/types/genesis_test.go
create x/did/types/keys.go
create x/did/types/params.go
create x/did/types/types.go
  • Create a message type createDID with fields: did, didDocString and createdAt :
$ starport scaffold message createDID did didDocString createdAt --module did

modify proto/did/tx.proto
modify x/did/client/cli/tx.go
create x/did/client/cli/tx_create_did.go
modify x/did/handler.go
create x/did/keeper/msg_server_create_did.go
modify x/did/module_simulation.go
create x/did/simulation/create_did.go
modify x/did/types/codec.go
create x/did/types/message_create_did.go
create x/did/types/message_create_did_test.go

🎉 Created a message `createDID`.
  • proto/did/tx.proto
syntax = "proto3";
package hypersignprotocol.hidnode.did;

// this line is used by starport scaffolding # proto/tx/import

option go_package = "github.com/hypersign-protocol/hid-node/x/did/types";

// Msg defines the Msg service.
service Msg {
      rpc CreateDID(MsgCreateDID) returns (MsgCreateDIDResponse);
// this line is used by starport scaffolding # proto/tx/rpc
}

message MsgCreateDID {
  string creator = 1;
  string did = 2;
  string didDocString = 3;
  string createdAt = 4;
}

message MsgCreateDIDResponse {
  uint64 id = 1;
}

// this line is used by starport scaffolding # proto/tx/message
  • x/did/keeper/msg_server_create_did.go
package keeper

import (
	"context"

	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/hypersign-protocol/hid-node/x/did/types"
)

func (k msgServer) CreateDID(goCtx context.Context, msg *types.MsgCreateDID) (*types.MsgCreateDIDResponse, error) {
	ctx := sdk.UnwrapSDKContext(goCtx)

	var didSpec = types.DidSpec{
		Creator:      msg.Creator,
		Did:          msg.Did,
		DidDocString: msg.DidDocString,
		CreatedAt:    msg.CreatedAt,
	}
	// Add a DID to the store and get back the ID
	id := k.AppendDID(ctx, didSpec)
	// Return the Id of the DID
	return &types.MsgCreateDIDResponse{Id: id}, nil
}
  • proto/did/didSpec.proto
syntax = "proto3";
package hypersignprotocol.hidnode.did;
option go_package = "github.com/hypersign-protocol/hid-node/x/did/types";

message DidSpec {
  string creator = 1;
  uint64 id = 2;
  string did = 3;
  string didDocString = 4; 
  string createdAt = 5;
}
  • x/did/types/keys.go - Append the following:
const (
	DidKey      = "Did-value-"
	DidCountKey = "Did-count-"
)
  • x/did/keeper/didSpec.go - The AppendDID function registers the DID in the Key Value store.
package keeper

import (
	"encoding/binary"

	"github.com/cosmos/cosmos-sdk/store/prefix"
	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/hypersign-protocol/hid-node/utils"
	"github.com/hypersign-protocol/hid-node/x/did/types"
)

func (k Keeper) GetDidCount(ctx sdk.Context) uint64 {
	// Get the store using storeKey (which is "blog") and PostCountKey (which is "Post-count-")
	store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DidCountKey))
	// Convert the PostCountKey to bytes
	byteKey := []byte(types.DidCountKey)
	// Get the value of the count
	bz := store.Get(byteKey)
	// Return zero if the count value is not found (for example, it's the first post)
	if bz == nil {
		return 0
	}
	// Convert the count into a uint64
	return binary.BigEndian.Uint64(bz)
}

func (k Keeper) SetDidCount(ctx sdk.Context, count uint64) {
	// Get the store using storeKey (which is "blog") and PostCountKey (which is "Post-count-")
	store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DidCountKey))
	// Convert the PostCountKey to bytes
	byteKey := []byte(types.DidCountKey)
	// Convert count from uint64 to string and get bytes
	bz := make([]byte, 8)
	binary.BigEndian.PutUint64(bz, count)
	// Set the value of Post-count- to count
	store.Set(byteKey, bz)
}

func (k Keeper) AppendDID(ctx sdk.Context, didSpec types.DidSpec) uint64 {
	// Get the current number of posts in the store
	count := k.GetDidCount(ctx)
	// Assign an ID to the post based on the number of posts in the store
	didSpec.Id = count
	// Get the store
	store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DidKey))
	// Convert the post ID into bytes
	byteKey := make([]byte, 8)
	binary.BigEndian.PutUint64(byteKey, didSpec.Id)
	// Marshal the post into bytes
	appendedValue := k.cdc.MustMarshal(&didSpec)
	// Insert the post bytes using post ID as a key

	store.Set(utils.UnsafeStrToBytes(didSpec.Did), appendedValue)
	// Update the post count
	k.SetDidCount(ctx, count+1)
	return count
}
  • utils/string.go - The script has functions to convert String to Bytes and vice versa
  • Now, we need to build a Query service to query DIDs

To build a Query service:

$ starport scaffold query dids --response did,didDocString,createdAt
  • proto/did/query.proto
syntax = "proto3";
package hypersignprotocol.hidnode.did;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "did/params.proto";
import "did/didSpec.proto";
// this line is used by starport scaffolding # 1

option go_package = "github.com/hypersign-protocol/hid-node/x/did/types";

// Query defines the gRPC querier service.
service Query {
  // Parameters queries the parameters of the module.
  rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
    option (google.api.http).get = "/hypersignprotocol/hidnode/did/params";
  }
  // Queries a list of Dids items.
	rpc Dids(QueryDidsRequest) returns (QueryDidsResponse) {
		option (google.api.http).get = "/hypersign-protocol/hidnode/did/{did}";
	}

// this line is used by starport scaffolding # 2
}

// QueryParamsRequest is request type for the Query/Params RPC method.
message QueryParamsRequest {}

// QueryParamsResponse is response type for the Query/Params RPC method.
message QueryParamsResponse {
  // params holds all the parameters of this module.
  Params params = 1 [(gogoproto.nullable) = false];
}

message QueryDidsRequest {
  string did = 1;
}

message QueryDidsResponse {
  string didDoc = 1;
}

// this line is used by starport scaffolding # 3
  • x/did/grpc_query_dids.go - In the function Dids, we are taking the input DID (Blockchain API endpoint /dids/{did}), and using it as a key to retrieve its corresponding value from the Key Value Store . In our case, the value is didDoc.
package keeper

import (
	"context"

	"github.com/cosmos/cosmos-sdk/store/prefix"
	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/hypersign-protocol/hid-node/utils"
	"github.com/hypersign-protocol/hid-node/x/did/types"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func (k Keeper) Dids(goCtx context.Context, req *types.QueryDidsRequest) (*types.QueryDidsResponse, error) {
	if req == nil {
		return nil, status.Error(codes.InvalidArgument, "invalid request")
	}

	// Get context with the information about the environment
	ctx := sdk.UnwrapSDKContext(goCtx)
	// Get the key-value module store using the store key (in our case store key is "chain")
	store := ctx.KVStore(k.storeKey)
	// Get the part of the store that keeps posts (using post key, which is "Post-value-")
	didStore := prefix.NewStore(store, []byte(types.DidKey))
	bz := didStore.Get(utils.UnsafeStrToBytes(req.Did))

	// Return a struct containing a list of posts and pagination info
	return &types.QueryDidsResponse{DidDoc: utils.UnsafeBytesToStr(bz)}, nil
}
  • x/did/module.go - Registering the
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
    types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
}

@arnabghose997
Copy link

The prominent libraries used in Golang for cryptography are:

import (
    "crypto/ed25519"
    "encoding/base64"
)

Following are the lengths for key sizes:

//File ed25519.go

const (
	// PublicKeySize is the size, in bytes, of public keys as used in this package.
	PublicKeySize = 32
	// PrivateKeySize is the size, in bytes, of private keys as used in this package.
	PrivateKeySize = 64
	// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
	SignatureSize = 64
	// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
	SeedSize = 32
)

@arnabghose997
Copy link

Following are the Sign and Verify implementations of ed25519 Golang library:

Sign

// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
    // Outline the function body so that the returned signature can be
    // stack-allocated.
    signature := make([]byte, SignatureSize)
    sign(signature, privateKey, message)
    return signature
}

func sign(signature, privateKey, message []byte) {
    if l := len(privateKey); l != PrivateKeySize {
        panic("ed25519: bad private key length: " + strconv.Itoa(l))
    }
    seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]

    h := sha512.Sum512(seed)
    s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
    prefix := h[32:]

    mh := sha512.New()
    mh.Write(prefix)
    mh.Write(message)
    messageDigest := make([]byte, 0, sha512.Size)
    messageDigest = mh.Sum(messageDigest)
    r := edwards25519.NewScalar().SetUniformBytes(messageDigest)

    R := (&edwards25519.Point{}).ScalarBaseMult(r)

    kh := sha512.New()
    kh.Write(R.Bytes())
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S := edwards25519.NewScalar().MultiplyAdd(k, s, r)

    copy(signature[:32], R.Bytes())
    copy(signature[32:], S.Bytes())
}

Verify

// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
    if l := len(publicKey); l != PublicKeySize {
        panic("ed25519: bad public key length: " + strconv.Itoa(l))
    }

    if len(sig) != SignatureSize || sig[63]&224 != 0 {
        return false
    }

    A, err := (&edwards25519.Point{}).SetBytes(publicKey)
    if err != nil {
        return false
    }

    kh := sha512.New()
    kh.Write(sig[:32])
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
    if err != nil {
        return false
    }

    // [S]B = R + [k]A --> [k](-A) + [S]B = R
    minusA := (&edwards25519.Point{}).Negate(A)
    R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)

    return bytes.Equal(sig[:32], R.Bytes())
}

@Vishwas1
Copy link
Contributor Author

Vishwas1 commented Feb 9, 2022

Following are the Sign and Verify implementations of ed25519 Golang library:

Sign

// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
    // Outline the function body so that the returned signature can be
    // stack-allocated.
    signature := make([]byte, SignatureSize)
    sign(signature, privateKey, message)
    return signature
}

func sign(signature, privateKey, message []byte) {
    if l := len(privateKey); l != PrivateKeySize {
        panic("ed25519: bad private key length: " + strconv.Itoa(l))
    }
    seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]

    h := sha512.Sum512(seed)
    s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
    prefix := h[32:]

    mh := sha512.New()
    mh.Write(prefix)
    mh.Write(message)
    messageDigest := make([]byte, 0, sha512.Size)
    messageDigest = mh.Sum(messageDigest)
    r := edwards25519.NewScalar().SetUniformBytes(messageDigest)

    R := (&edwards25519.Point{}).ScalarBaseMult(r)

    kh := sha512.New()
    kh.Write(R.Bytes())
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S := edwards25519.NewScalar().MultiplyAdd(k, s, r)

    copy(signature[:32], R.Bytes())
    copy(signature[32:], S.Bytes())
}

Verify

// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
    if l := len(publicKey); l != PublicKeySize {
        panic("ed25519: bad public key length: " + strconv.Itoa(l))
    }

    if len(sig) != SignatureSize || sig[63]&224 != 0 {
        return false
    }

    A, err := (&edwards25519.Point{}).SetBytes(publicKey)
    if err != nil {
        return false
    }

    kh := sha512.New()
    kh.Write(sig[:32])
    kh.Write(publicKey)
    kh.Write(message)
    hramDigest := make([]byte, 0, sha512.Size)
    hramDigest = kh.Sum(hramDigest)
    k := edwards25519.NewScalar().SetUniformBytes(hramDigest)

    S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
    if err != nil {
        return false
    }

    // [S]B = R + [k]A --> [k](-A) + [S]B = R
    minusA := (&edwards25519.Point{}).Negate(A)
    R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)

    return bytes.Equal(sig[:32], R.Bytes())
}

@arnabghose997
I was wondering if you have executed them independently ? I mean imagine I have a message and I want to use those above codes to sign and verify the signature, can I do that ?

@arnabghose997
Copy link

@Vishwas1 Yes that's possible, but I just went through their implementation, instead of running them separately . While going through the cheqd-node code, I saw the usage of of these functions as ed25519.Sign() and ed25519.Verify().

@arnabghose997
Copy link

arnabghose997 commented Mar 3, 2022

Info for Coin Metadata : https://docs.cosmos.network/master/architecture/adr-024-coin-metadata.html

Cosmos Chain Registry (Metadata about all Cosmos Chains): https://github.com/cosmos/chain-registry/

Genesis File for Reference: https://github.com/persistenceOne/networks/blob/master/test-core-1/final_genesis.json

This forum post will serve as a good reference while going for testnet: https://forum.cosmos.network/t/using-an-aws-ec2-as-a-cosmos-node/845

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants