Didexchange using InboundTransport for running 2 agents in localhost using aries-framework-go

213 Views Asked by At

I'm new to aries and I'm running an example of the code but I haven't been able to stablish a connection using the didexchange protocol.

I am creating two services using go, one running on port 5000 and other at 5005.

Here's my code:

func main() {
    client, _ := services.NewDidClient(port)

    http.Handle("/invitation", &handlers.InvitationHandler{DidClient: *client})
    http.Handle("/connection", &handlers.ConnectionHandler{DidClient: *client})
    http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

type DidClient struct {
    didexchange.Client
}
func NewDidClient(port int32) (*DidClient, error) {
    framework, _ := aries.New(
        // aries.WithInboundTransport(newInboundTransport(port)),
        aries.WithStoreProvider(mem.NewProvider()),
        aries.WithProtocolStateStoreProvider(mem.NewProvider()),
    )
    ctx, _ := framework.Context()
    didExchangeClient, _ := didexchange.New(ctx)
    actions := make(chan service.DIDCommAction, 1)
    didExchangeClient.RegisterActionEvent(actions)
    go func() {
        service.AutoExecuteActionEvent(actions)
    }()
    return &DidClient{Client: *didExchangeClient}, nil
}

type InvitationHandler struct {
    DidClient services.DidClient
}
func (handler *InvitationHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
    switch request.Method {
    case http.MethodGet:
        invitation, _ := handler.DidClient.CreateInvitation("5000 invitation")  
        response, _ := json.Marshal(invitation)     
        writer.Header().Set("Content-Type", "application/json")
        writer.Write(response)
    }
}

type ConnectionHandler struct {
    DidClient services.DidClient
}
func (handler *ConnectionHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
    switch request.Method {
    case http.MethodGet:
        connections, _ := handler.DidClient.QueryConnections(&didexchange.QueryConnectionsParams{})
        response, _ := json.Marshal(connections)
        writer.Header().Set("Content-Type", "application/json")
        writer.Write(response)

    case http.MethodPost:
        var invitation didexchange.Invitation
        bodyBytes, _ := ioutil.ReadAll(request.Body)
        json.Unmarshal(bodyBytes, &invitation)  
        connectionID, _ := handler.DidClient.HandleInvitation(&invitation)
        connection, _ := handler.DidClient.GetConnection(connectionID)
        response, _ := json.Marshal(connection)
        writer.Header().Set("Content-Type", "application/json")
        writer.Write(response)
    }
}

type inboundTransport struct {
    port int32
}

func newInboundTransport(port int32) *inboundTransport {
    return &inboundTransport{port: port + 1}
}

func (transport *inboundTransport) Start(prov transport.Provider) error {
    return nil
}

func (transport *inboundTransport) Stop() error {
    return nil
}

func (transport *inboundTransport) Endpoint() string {
    return fmt.Sprintf("http://localhost:%d", transport.port) 
}

I'm omiting the error handling here but I have it in my code.

So, running without the inbound transport they both say that the service endpoint is this: didcomm:transport/queue

I create an invitation using the invitation handler on port 5000, like this:

curl --request GET --url http://localhost:5000/invitation
response: 
{
  "serviceEndpoint": "didcomm:transport/queue",
  "recipientKeys": [
    "did:key:z6MkojtSLJ4EtwAUJZsy7BDhhDDnNtfvwu3AH7di6o5XzaFz"
  ],
  "@id": "ac56543b-526b-47e6-887a-0ee4a8fd888e",
  "label": "5000 invitation",
  "@type": "https://didcomm.org/didexchange/1.0/invitation"
}

pass it to the agent in port 5005 using post in the connection handler like this:

curl --request POST \
  --url http://localhost:5005/connection \
  --header 'Content-Type: application/json' \
  --data '{
  "serviceEndpoint": "didcomm:transport/queue",
  "recipientKeys": [
    "did:key:z6MkojtSLJ4EtwAUJZsy7BDhhDDnNtfvwu3AH7di6o5XzaFz"
  ],
  "@id": "ac56543b-526b-47e6-887a-0ee4a8fd888e",
  "label": "5000 invitation",
  "@type": "https://didcomm.org/didexchange/1.0/invitation"
}'
response:
{
  "ConnectionID": "808939bc-0e88-41cb-971b-e00e3aa2a631",
  "State": "null",
  "ThreadID": "3db73089-025d-4e6f-9703-d86881745494",
  "ParentThreadID": "",
  "TheirLabel": "5000 invitation",
  "TheirDID": "",
  "MyDID": "",
  "ServiceEndPoint": "didcomm:transport/queue",
  "RecipientKeys": [
    "did:key:z6Mknaw7ANj5yqDrsFhkWgfdYM8XbGNKLLexhBmD1XoUKAAo"
  ],
  "RoutingKeys": null,
  "InvitationID": "3db73089-025d-4e6f-9703-d86881745494",
  "InvitationDID": "",
  "Implicit": false,
  "Namespace": "my"
}

And I was expecting to get a connection in both agents running the connection get, but the connection is only on the 5005 agent, like this:

curl --request GET --url http://localhost:5000/connection
response: nil

curl --request GET --url http://localhost:5005/connection
response:
[{
  "ConnectionID": "808939bc-0e88-41cb-971b-e00e3aa2a631",
  "State": "abandoned",
  "ThreadID": "3db73089-025d-4e6f-9703-d86881745494",
  "ParentThreadID": "",
  "TheirLabel": "5000 invitation",
  "TheirDID": "",
  "MyDID": "did:peer:1zQmPBE2GKCCWTXoSA2EzUVbLGs3njJtqDmnN5LLP9UQpWLJ",
  "ServiceEndPoint": "didcomm:transport/queue",
  "RecipientKeys": [
    "did:key:z6Mknaw7ANj5yqDrsFhkWgfdYM8XbGNKLLexhBmD1XoUKAAo"
  ],
  "RoutingKeys": null,
  "InvitationID": "3db73089-025d-4e6f-9703-d86881745494",
  "InvitationDID": "",
  "Implicit": false,
  "Namespace": "my"
}]

But I'm getting these errors on the console:

[aries-framework/out-of-band/service] 2021/08/26 02:11:15 UTC - n/a -> ERROR command=[out-of-band] action=handleDIDEvent] [] errMsg=[ignored]

The connection in agent 5005 says its abandonned, and I think the problem its that both frameworks should be able to connect whith each other without my intervention but they cannot see each other, so I added the InboundTransport to each using http://localhost with ports 5001 and 5006, but then I got these errors:

[aries-framework/out-of-band/service] 2021/08/26 02:20:41 UTC - n/a -> ERROR command=[out-of-band] action[handleDIDEvent] [] errMsg=[ignored]
[aries-framework/http] 2021/08/26 02:20:44 UTC - http.(*OutboundHTTPClient).Send -> ERROR posting DID envelope to agent failed [http://localhost:5001, Post "http://localhost:5001": dial tcp [::1]:5001: connectex: No connection could be made because the target machine actively refused it.]
[aries-framework/out-of-band/service] 2021/08/26 02:20:44 UTC - n/a -> ERROR command=[out-of-band] action [handleDIDEvent] [] errMsg=[ignored]

So, I'm a little lost, I read that the agents should work with only the new() (with batteries) but I'm not sure if running both agents in my localhost is making them in conflict, and how does "didcomm:transport/queue" work? I get that the framework is not using rest and its embebbed with go, but then, how does it expose its endpoints? what am I missing?

Thanks

1

There are 1 best solutions below

1
On BEST ANSWER

I posted the question as a github issue and with the help of the references they posted I changed my code and got the inbound working.

Here are the changes:

func NewDidClient(port int32) (*DidClient, error) {

    address := fmt.Sprintf("localhost:%d", port + 1)
    inbound, err := ws.NewInbound(address, "ws://" + address, "", "")

    framework, _ := aries.New(
        aries.WithInboundTransport(inbound),
        aries.WithOutboundTransports(ws.NewOutbound()),
        aries.WithStoreProvider(mem.NewProvider()),
        aries.WithProtocolStateStoreProvider(mem.NewProvider()),
    )
    ctx, _ := framework.Context()
    didExchangeClient, _ := didexchange.New(ctx)
    actions := make(chan service.DIDCommAction, 1)
    didExchangeClient.RegisterActionEvent(actions)
    go func() {
        service.AutoExecuteActionEvent(actions)
    }()
    return &DidClient{Client: *didExchangeClient}, nil
}

It uses websockets and now both agents can connect with each other.