Closed Vishwas1 closed 2 years ago
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
PR Reference: hypersign-protocol/hid-node#2
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
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 versaQuery
service to query DIDsTo 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 thefunc (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
}
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
)
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())
}
Following are the
Sign
andVerify
implementations ofed25519
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 ?
@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()
.
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
Requirement
Tasks
HID-core
did
module using startport cli on HID-dev the way they have scaffolded blog module in their doc. Use this schema