Skip to content

Commit

Permalink
revert "chore: remove update did state transition" (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
noandrea authored Feb 23, 2022
1 parent 49890ac commit 85e6d16
Show file tree
Hide file tree
Showing 14 changed files with 21,945 additions and 604 deletions.
20,798 changes: 20,291 additions & 507 deletions docs/Reference/swagger/swagger-ui/swagger.yaml

Large diffs are not rendered by default.

670 changes: 670 additions & 0 deletions docs/static/openapi.yml

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions proto/did/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ option go_package = "github.com/elesto-dao/elesto/x/did";
service Msg {
// CreateDidDocument defines a method for creating a new identity.
rpc CreateDidDocument(MsgCreateDidDocument) returns (MsgCreateDidDocumentResponse);
// UpdateDidDocument defines a method for updating an identity.
rpc UpdateDidDocument(MsgUpdateDidDocument) returns (MsgUpdateDidDocumentResponse);

// AddVerificationMethod adds a new verification method
rpc AddVerification(MsgAddVerification) returns (MsgAddVerificationResponse);
Expand Down Expand Up @@ -58,6 +60,17 @@ message MsgCreateDidDocument {

message MsgCreateDidDocumentResponse {}

// MsgUpdateDidDocument replace an existing did document with a new version
message MsgUpdateDidDocument {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

DidDocument doc = 1; // the did document to replace
string signer = 5; // address of the account signing the message
}

message MsgUpdateDidDocumentResponse {}

// -------------------------------
// Verification methods / relations
// -------------------------------
Expand Down
1 change: 1 addition & 0 deletions x/did/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
// this line is used by starport scaffolding # 3
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgCreateDidDocument{},
&MsgUpdateDidDocument{},
&MsgAddVerification{},
&MsgSetVerificationRelationships{},
&MsgRevokeVerification{},
Expand Down
24 changes: 24 additions & 0 deletions x/did/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,30 @@ func (k msgServer) CreateDidDocument(
return &didmod.MsgCreateDidDocumentResponse{}, nil
}

// UpdateDidDocument update an existing DID document
func (k msgServer) UpdateDidDocument(
goCtx context.Context,
msg *didmod.MsgUpdateDidDocument,
) (*didmod.MsgUpdateDidDocumentResponse, error) {

if err := executeOnDidWithRelationships(
goCtx, &k.Keeper,
didmod.VerificationRelationships{didmod.Authentication},
msg.Doc.Id, msg.Signer,
//XXX: check this assignment during audit
//nolint
func(didDoc *didmod.DidDocument) error {
if !didmod.IsValidDIDDocument(msg.Doc) {
return sdkerrors.Wrapf(didmod.ErrInvalidDIDFormat, "invalid did document")
}
didDoc = msg.Doc
return nil
}); err != nil {
return nil, err
}
return &didmod.MsgUpdateDidDocumentResponse{}, nil
}

// AddVerification adds a verification method and it's relationships to a DID Document
func (k msgServer) AddVerification(
goCtx context.Context,
Expand Down
131 changes: 131 additions & 0 deletions x/did/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,137 @@ func (suite *KeeperTestSuite) TestHandleMsgCreateDidDocument() {
}
}

func (suite *KeeperTestSuite) TestHandleMsgUpdateDidDocument() {
var (
req didmod.MsgUpdateDidDocument
errExp error
)

server := NewMsgServerImpl(suite.keeper)

testCases := []struct {
name string
malleate func()
}{
{
"FAIL: not found",
func() {
req = *didmod.NewMsgUpdateDidDocument(&didmod.DidDocument{Id: "did:cosmos:net:elesto:subject"}, "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
errExp = sdkerrors.Wrapf(didmod.ErrDidDocumentNotFound, "did document at %s not found", "did:cosmos:net:elesto:subject")
},
},
{
"FAIL: unauthorized",
func() {

did := "did:cosmos:net:elesto:subject"
didDoc, _ := didmod.NewDidDocument(did)
suite.keeper.SetDidDocument(suite.ctx, []byte(didDoc.Id), didDoc)

req = *didmod.NewMsgUpdateDidDocument(&didmod.DidDocument{Id: didDoc.Id, Controller: []string{"did:cosmos:cash:controller"}}, "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
errExp = sdkerrors.Wrapf(didmod.ErrUnauthorized, "signer account %s not authorized to update the target did document at %s", "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8", did)

},
},
{
"PASS: replace did document",
func() {

did := "did:cosmos:net:elesto:subject"
didDoc, _ := didmod.NewDidDocument(did, didmod.WithVerifications(
didmod.NewVerification(
didmod.NewVerificationMethod(
"did:cosmos:net:elesto:subject#key-1",
"did:cosmos:net:elesto:subject",
didmod.NewPublicKeyMultibase([]byte{3, 223, 208, 164, 105, 128, 109, 102, 162, 60, 124, 148, 143, 85, 193, 41, 70, 125, 109, 9, 116, 162, 34, 239, 110, 36, 165, 56, 250, 104, 130, 243, 215}),
didmod.EcdsaSecp256k1VerificationKey2019,
),
[]string{didmod.Authentication},
nil,
),
))
suite.keeper.SetDidDocument(suite.ctx, []byte(didDoc.Id), didDoc)
suite.keeper.SetDidMetadata(suite.ctx, []byte(didDoc.Id), didmod.NewDidMetadata([]byte{1}, time.Now()))

newDidDoc, err := didmod.NewDidDocument(did)
suite.Require().Nil(err)

req = *didmod.NewMsgUpdateDidDocument(&newDidDoc, "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
errExp = nil
},
},
{
"FAIL: invalid controllers",
func() {
didDoc, _ := didmod.NewDidDocument("did:cosmos:net:elesto:subject", didmod.WithVerifications(
didmod.NewVerification(
didmod.NewVerificationMethod(
"did:cosmos:net:elesto:subject#key-1",
"did:cosmos:net:elesto:subject",
didmod.NewPublicKeyMultibase([]byte{3, 223, 208, 164, 105, 128, 109, 102, 162, 60, 124, 148, 143, 85, 193, 41, 70, 125, 109, 9, 116, 162, 34, 239, 110, 36, 165, 56, 250, 104, 130, 243, 215}),
didmod.EcdsaSecp256k1VerificationKey2019,
),
[]string{didmod.Authentication},
nil,
),
))
suite.keeper.SetDidDocument(suite.ctx, []byte(didDoc.Id), didDoc)

controllers := []string{
"did:cosmos:cash:controller-1",
"did:cosmos:cash:controller-2",
"invalid",
}

req = *didmod.NewMsgUpdateDidDocument(&didmod.DidDocument{Id: didDoc.Id, Controller: controllers}, "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
errExp = sdkerrors.Wrapf(didmod.ErrInvalidDIDFormat, "invalid did document")
},
},
{
"FAIL: did is of type key (1)",
func() {
did := "did:cosmos:key:cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8"
didDoc, _ := didmod.NewDidDocument(did)
controllers := []string{
"did:cosmos:cash:controller-1",
"did:cosmos:cash:controller-2",
}

req = *didmod.NewMsgUpdateDidDocument(&didmod.DidDocument{Id: didDoc.Id, Controller: controllers}, "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
errExp = sdkerrors.Wrapf(didmod.ErrInvalidInput, "did documents having id with key format are read only %s", did)
},
},
{
"FAIL: did is of type key (2)",
func() {
did := "did:cosmos:key:juno1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8"
didDoc, _ := didmod.NewDidDocument(did)
controllers := []string{
"did:cosmos:cash:controller-1",
"did:cosmos:cash:controller-2",
}

req = *didmod.NewMsgUpdateDidDocument(&didmod.DidDocument{Id: didDoc.Id, Controller: controllers}, "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
errExp = sdkerrors.Wrapf(didmod.ErrInvalidInput, "did documents having id with key format are read only %s", did)
},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
tc.malleate()

_, err := server.UpdateDidDocument(sdk.WrapSDKContext(suite.ctx), &req)

if errExp == nil {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
suite.Require().Equal(errExp.Error(), err.Error())
}
})
}
}

func (suite *KeeperTestSuite) TestHandleMsgAddVerification() {
var (
req didmod.MsgAddVerification
Expand Down
43 changes: 43 additions & 0 deletions x/did/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,49 @@ func (msg MsgCreateDidDocument) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{accAddr}
}

// --------------------------
// UPDATE IDENTIFIER
// --------------------------

// msg types
const (
TypeMsgUpdateDidDocument = "update-did"
)

func NewMsgUpdateDidDocument(
didDoc *DidDocument,
signerAccount string,
) *MsgUpdateDidDocument {
return &MsgUpdateDidDocument{
Doc: didDoc,
Signer: signerAccount,
}
}

// Route implements sdk.Msg
func (MsgUpdateDidDocument) Route() string {
return RouterKey
}

// Type implements sdk.Msg
func (MsgUpdateDidDocument) Type() string {
return TypeMsgUpdateDidDocument
}

// GetSignBytes implements the LegacyMsg.GetSignBytes method.
func (MsgUpdateDidDocument) GetSignBytes() []byte {
panic("TODO: needed in simulations for fuzz testing")
}

// GetSigners implements sdk.Msg
func (msg MsgUpdateDidDocument) GetSigners() []sdk.AccAddress {
accAddr, err := sdk.AccAddressFromBech32(msg.Signer)
if err != nil {
panic(err)
}
return []sdk.AccAddress{accAddr}
}

// --------------------------
// ADD VERIFICATION
// --------------------------
Expand Down
26 changes: 26 additions & 0 deletions x/did/msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@ func TestMsgCreateDidDocument_GetSigners(t *testing.T) {
assert.Panics(t, func() { MsgCreateDidDocument{Signer: "invalid"}.GetSigners() })
}

// --------------------------
// UPDATE IDENTIFIER
// --------------------------

func TestMsgUpdateDidDocument_Route(t *testing.T) {
assert.Equalf(t, ModuleName, MsgUpdateDidDocument{}.Route(), "Route()")
}

func TestMsgUpdateDidDocument_Type(t *testing.T) {
assert.Equalf(t, TypeMsgUpdateDidDocument, MsgUpdateDidDocument{}.Type(), "Type()")
}

func TestMsgUpdateDidDocument_GetSignBytes(t *testing.T) {
assert.Panicsf(t, func() { MsgUpdateDidDocument{}.GetSignBytes() }, "GetSignBytes()")
}

func TestMsgUpdateDidDocument_GetSigners(t *testing.T) {
a, err := sdk.AccAddressFromBech32("cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8")
assert.NoError(t, err)
assert.Equal(t,
MsgUpdateDidDocument{Signer: "cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8"}.GetSigners(),
[]sdk.AccAddress{a},
)
assert.Panics(t, func() { MsgUpdateDidDocument{Signer: "invalid"}.GetSigners() })
}

// --------------------------
// ADD VERIFICATION
// --------------------------
Expand Down
19 changes: 19 additions & 0 deletions x/did/msg_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ func (msg MsgCreateDidDocument) ValidateBasic() error {

}

// --------------------------
// UPDATE IDENTIFIER
// --------------------------

// ValidateBasic performs a basic check of the MsgUpdateDidDocument fields.
func (msg MsgUpdateDidDocument) ValidateBasic() error {
if !IsValidDID(msg.Doc.Id) {
return sdkerrors.Wrap(ErrInvalidDIDFormat, msg.Doc.Id)
}

for _, c := range msg.Doc.Controller {
// if controller is set must be compliant
if !IsValidDID(c) {
return sdkerrors.Wrap(ErrInvalidDIDFormat, "controller validation error")
}
}
return nil
}

// --------------------------
// ADD VERIFICATION METHOD
// --------------------------
Expand Down
60 changes: 60 additions & 0 deletions x/did/msg_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,66 @@ func TestMsgCreateDidDocument(t *testing.T) {
}
}

func TestMsgUpdateDidDocument(t *testing.T) {
tests := []struct {
id string
controllers []string
signer string
expectPass bool
}{
{
"did:cosmos:net:elesto:subject",
[]string{"did:cosmos:controller-1"},
"cosmos1uam3kpjdx3wksx46lzq6y628wwyzv0guuren75",
true,
},
{
"did:cosmos:net:elesto:subject",
[]string{},
"cosmos1uam3kpjdx3wksx46lzq6y628wwyzv0guuren75",
true,
},
{
// FIXME: duplicated controller
"did:cosmos:net:elesto:subject",
[]string{"did:cosmos:controller-1", "did:cosmos:controller-1"},
"cosmos1uam3kpjdx3wksx46lzq6y628wwyzv0guuren75",
true,
},
{
"invalid did",
[]string{"did:cosmos:controller-1"},
"cosmos1uam3kpjdx3wksx46lzq6y628wwyzv0guuren75",
false, // invalid did
},
{
"did:cosmos:net:elesto:subject",
[]string{"invalid:controller"},
"cosmos1uam3kpjdx3wksx46lzq6y628wwyzv0guuren75",
false, // invalid controller
},
{
"did:cosmos:net:elesto:subject",
[]string{"did:cosmos:controller-1", "did:cosmos:controller-2", ""},
"cosmos1uam3kpjdx3wksx46lzq6y628wwyzv0guuren75",
false, // invalid controller
},
}

for i, tc := range tests {
msg := NewMsgUpdateDidDocument(
&DidDocument{Id: tc.id, Controller: tc.controllers},
tc.signer,
)

if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: TestMsgUpdateDidDocument#%v", i)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: TestMsgUpdateDidDocument#%v", i)
}
}
}

func TestMsgAddVerification(t *testing.T) {
tests := []struct {
id string
Expand Down
Loading

0 comments on commit 85e6d16

Please sign in to comment.