-
Notifications
You must be signed in to change notification settings - Fork 162
feat: Protocols can use DIDs to identify the agents they communicate with #938
Conversation
BDD tests are currently broken, but review from @soluchok is needed, for the interface this provides to protocols. |
9385017
to
03369ac
Compare
Current API this PR creates: This saves the correlation/connection between another agent's peer DID/keys, and the peer DID your agent uses to communicate with them. DIDExchange uses this to save the connection information when the protocol succeeds. To get the But why would you, when you can call SendToDID on the outbound dispatcher, and also skip determining your sender key:
And for inbound messages, I still have to write a lot of tests and then bugfix, but any feedback is welcome. |
@@ -16,7 +16,7 @@ import ( | |||
// Handler provides protocol service handle api. | |||
type Handler interface { | |||
// HandleInbound handles inbound messages. | |||
HandleInbound(msg *DIDCommMsg) (string, error) | |||
HandleInbound(msg *DIDCommMsg, myDID string, theirDID string) (string, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like my myDID is redundant. We can get my myDID using a GetDID
function. e.g
myDID := GetDID(theirDID)
. According to that line https://github.com/hyperledger/aries-framework-go/pull/938/files#diff-b429c177e8c9b423d01fcc0d7d2383e9R81
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn’t be guaranteed. An agent could have multiple connections to the same “theirDIDs” with different “myDIDs”.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but it is a map. I mean only two DIDs can be related to each other. According to code we have. See link ^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise GetDID(theirDID) should return a list of myDids. Which means you can use any of them. Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit confused. Why do we need multiple myDIDs by theirDid ? If the connection is established it doesn’t make sense to create one more. I am ok to create one more connection but with different DIDs pair (with the same agent)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's useful for communicating with a public DID - you might want multiple DIDs you can use to communicate with them, for privacy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A Lookup function is needed in the didconnection package to make this more useful. See prior comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since myDID and theirDID are parameters to HandleInbound, we don't need the theirDID -> myDID map. As parameters to HandleInbound, the DIDs can now be any values for any connection, even if theirDID is used in multiple connections.
} | ||
|
||
// SendToDID sends a message from myDID to the agent who owns theirDID | ||
func (o *OutboundDispatcher) SendToDID(msg interface{}, myDID, theirDID string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function also can be optimized. We can get myDID from DIDConnectionStore
by theirDID. It would be easy to use.
e.g SendToDID(msg interface{}, theirDID string)
and better to add a comment like function must be used after the connection was successfully established between two agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Public DIDs, which we can use multiple peer DIDs to communicate with, means we can't actually do this mapping in all cases. I've added support for providing "myDID" to the inbound handler in a service.
2374d91
to
e3409a0
Compare
Tests are passing, meaning it's time to write more tests. |
"github.com/hyperledger/aries-framework-go/pkg/storage" | ||
) | ||
|
||
// BaseDIDConnectionStore stores DIDs indexed by key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the prefix Base?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another name would be welcome - Store
is the interface name, and I didn't want a stuttering name. I can pull the interface out into an api package in the framework (which would allow this struct type to be named Store
), though the interface is only necessary to allow mocking, and isn't intended to be implemented and injected by the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a package's only purpose is to implement a struct, it is okay to have that stutter.
I don't think Base
adds any value.
(I'm also not understanding the conflict with the Store interface defined in another package?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conflict would be with the interface in the same package - didconnection.Store
in didconnection/api.go
. But I've renamed to ConnectionStore so there's no conflict.
pkg/didcomm/dispatcher/outbound.go
Outdated
} | ||
|
||
const ( | ||
ed25519KeyType = "Ed25519VerificationKey2018" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume hardcoding the key type is temporary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can make a TODO and issue - this question extends beyond the scope of this PR, and I aimed to just carry over the current design with these constants. The key type needs to be flexible, and our resolution of keys from DID docs seems to already support multiple key types, but these constants need to be replaced by another system (the communication layer recognizing the key type being used by the connection, and fetching the appropriate keys from DID docs).
require.NoError(t, err) | ||
require.Equal(t, msgIn, msgOut) | ||
require.Equal(t, base58.Encode(sendKey), encSign) | ||
// this won't work, since input keys and output keys to this Packer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what’s the resolution to this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JWE packer would need to be changed to use the same key format as Pack()
parameters and Unpack()
return values, so the keys returned by Unpack()
are keys passed into Pack()
rather than the Curve25519 conversions of given Ed25519 keys. With an agent that supports multiple formats for encryption keys, we could do this - enforce that the JWE packer uses Curve25519 keys as parameters/return values, and that it only be chosen for DIDComm channels that have Curve25519 pubkeys available on both ends.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a TODO?
@@ -404,6 +405,11 @@ func (ctx *context) getDIDDocAndConnection(pubDID string) (*did.Doc, *Connection | |||
return nil, nil, fmt.Errorf("resolve public did[%s]: %w", pubDID, err) | |||
} | |||
|
|||
err = ctx.connectionStore.didMap.SaveDIDFromDoc(didDoc, didCommServiceType, ed25519KeyType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 references above the func call might call for a refactor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will make an issue for this one - (permanent) connectionStore and the DIDConnection Store should be merged in another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
79efebe
to
7b620c3
Compare
Coverage almost there. Next, will merge in updates (generic connection store), and test that DIDs are saved correctly for resolution. |
ebe2068
to
aaf96cb
Compare
@@ -24,7 +24,8 @@ type Destination struct { | |||
|
|||
const ( | |||
didCommServiceType = "did-communication" | |||
ed25519KeyType = "Ed25519VerificationKey2018" | |||
// TODO: hardcoded key type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there more context on this TODO? Why hardcoded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we're using another key type for the communication, we need to remove the hardcoding of the key type and instead set it based on some connection parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created issue #1008
4df9a85
to
bd15b9b
Compare
@@ -415,6 +422,16 @@ func (ctx *context) getDIDDocAndConnection(pubDID string) (*did.Doc, *Connection | |||
return nil, nil, fmt.Errorf("create %s did: %w", didMethod, err) | |||
} | |||
|
|||
// TODO: initialize did map (or mock) in all eleventy billion tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
purged this check now.
framework initializes this properly, and we don't put checks in to catch broken tests.
didconnection.Store provides a lookup that lets you find a DID using one of its public keys. This currently only works for peer DIDs. Signed-off-by: Filip Burlacu <[email protected]>
Outbound: SendToDID resolves the target DID, and sends the message to the destination specified in the DID doc. Inbound: HandleInbound receives the DID of the sender and the DID you used to decrypt the message. Signed-off-by: Filip Burlacu <[email protected]>
Outbound: create a Destination struct from a DID using helper functions, so an agent can provide the DID of the target.
Inbound: receive the DID of the sender as a parameter to the message handler, if the sender has a DID doc in your VDRI.
Fixes #725