-
Notifications
You must be signed in to change notification settings - Fork 204
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
feat(core): connection-less issuance and verification #359
feat(core): connection-less issuance and verification #359
Conversation
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Codecov Report
@@ Coverage Diff @@
## main #359 +/- ##
==========================================
+ Coverage 86.52% 86.62% +0.10%
==========================================
Files 246 248 +2
Lines 5010 5198 +188
Branches 788 827 +39
==========================================
+ Hits 4335 4503 +168
- Misses 675 695 +20
Continue to review full report at Codecov.
|
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 think connectionless
instead of connection-less
might be better.
I used the notation as used in the Aries RFCs: https://github.com/hyperledger/aries-rfcs/search?q=connection-less |
Ah but seems google like connectionless better |
Ah yeah that makes sense then. |
This is awesome, I have not given this a thoroooough review yet, but I wanted to gauge/express concern over the naming on createOutOfBandOffer, since it could cause confusion/collision with the Out Of Band (OOB) invitations? What are your thoughts here @TimoGlastra? |
I actually think it matches perfectly with the OOB protocol. Out-Of-Band is a protocol to facilitate out-of-band exchange of messages. ACA-Py has it as a separate out-of-band topic but IMO it makes more sense to house them under the different modules. If we adopt OOB and want to issue a connectionless credentials, we can call the credentials module, which will actually return an OOB message with a credential offer inside of it. I think we can abstract the OOB protocol mostly away unless you have very specific requirements besides connection invitations, connectionless issuance/verification. Does my thinking make sense? |
I tend to agree with you here actually. I think having a separate module/service here for Out-Of-Band messages would be helpful, since it can do the bulk of the formatting and any needed storage (for non-connectionless). However I think other modules being able to use Out-Of-Band messages as you've outlined makes sense (essentially initiating the offer, but then collaborating with the OOB module to create the message). |
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 looks good to me--I would like to take another look after your updates here, specifically given some transport and mediation changes that I think are likely relevant.
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
@JamesKEbert Updated |
It was quite a hassle to merge. I think some pieces could be handled better, but I'd like to handle that in separate PRs and have some discussions about it first. Mainly:
So I'd like to merge in this state and make additional improvements in the future |
to prevent race conditions in the server being shutdown Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
packages/core/tests/helpers.ts
Outdated
filter((e) => state === undefined || e.payload.proofRecord.state === state), | ||
timeout(timeoutMs), | ||
catchError(() => { | ||
throw new Error(`ProofStateChanged event not emitted within specified timeout: { |
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 error message string is a little bit harder to read. Wouldn't be better to pass such info as an object into 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.
Error doesn't take additional arguments
messageSender.setOutboundTransporter(outboundTransporter) | ||
transportServiceFindServicesMock.mockReturnValue([]) | ||
|
||
await expect(messageSender.sendMessage(outboundMessage)).rejects.toThrow( | ||
`Connection with id test-123 has no service!` | ||
`Message is undeliverable to connection test-123 (Test 123)` |
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 if theirLabel
contains some malicious code? Are we protected against that? I'm not sure if it's safe to use theirLabel anywhere in the code 🤔
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 don't think that could cause any harm? thread id is also external. You mean like eval()
harm?
I'm not sure what makes this property different from the others. We're not doing any SQL / HTTP rendering
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.
Ok, sorry I was probably confused remembering some call where there was a discussion about the security of invitations.
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.
Wouldn't it be better to use connection.label
in such cases instead? I'm also a little bit confused what's the case for label
and theirLabel
🤔 😄
await this.messageSender.sendMessage(outboundMessage) | ||
} | ||
// Use ~service decorator otherwise | ||
else if (credentialRecord.credentialMessage?.service && credentialRecord.requestMessage?.service) { |
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'm not sure if it's good to write if statements in this way. It seems like a convention from C# but not common in JS language. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else#using_else_if
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'm not sure I fully understand. I've never heard that else if is an anti-pattern in JS.
However I'm that a big fan of this code. The if/else shouldn't be there in the first place. But until out-of-band I'd like to keep it there
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 mean this
}
// Use ~service decorator otherwise
else if
instead of
} else if {
// Use ~service decorator otherwise
}
const nonce = proofRequestOptions.nonce ?? (await this.proofService.generateProofRequestNonce()) | ||
|
||
const proofRequest = new ProofRequest({ | ||
name: proofRequestOptions.name ?? 'proof-request', | ||
version: proofRequestOptions.name ?? '1.0', | ||
nonce, | ||
requestedAttributes: proofRequestOptions.requestedAttributes, | ||
requestedPredicates: proofRequestOptions.requestedPredicates, | ||
}) |
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.
Shouldn't this be part of proofService.createRequest
service? It seems like duplication from another method calling proofService.createRequest
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 didn't want to make opinions about default values in the service. I'm not even sure we should set default values...
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.
So for now I'd like to keep it in the module (and have a discussion about the duplication during the AFJ call)
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.
ok
|
||
return { proofRecord, requestMessage: message } | ||
} | ||
|
||
/** | ||
* Accept a presentation request as prover (by sending a presentation message) to the connection | ||
* associated with the proof record. |
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 built JS doc blindness so I usually don't read it so much :) but I'm not sure if it's updated according to the changes.
const credentialRecordPromise = waitForCredentialRecord(holderAgent, { | ||
threadId: issuerCredentialRecord.threadId, | ||
state: CredentialState.OfferReceived, | ||
}) |
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 any benefit of making a Promise variable rather than awat
ing it later at line 400?
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'm in the progress of refactoring the method to work with observables. We need to start listening before calling the method that will emit the event. Otherwise we start listening potentially after the event has already been emitted. So we need to start the listener, make the function call and then await.
I've partly refactored some other call to use ReplaySubject so we can replay all events that came in.
I added a few notes, but it seems good overall 👍 I believe we're able to improve MessageSender. There is a lot of small duplication all over the class. It was hard for me to get oriented. |
Signed-off-by: Timo Glastra <[email protected]>
Definitely would like to improve the duplication in message sender |
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
I tend to agree on the complexity of the message sender, but I think I'm comfortable improving on that in subsequent PRs.
I think this is an important item/consideration ^ |
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 would be nice to merge it before adding support for mulitransports. It seems there is quite some logic in the same area.
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Timo Glastra <[email protected]>
Adds connection-less issuance and verification.
Agent.credentials.createOutOfBandOffer
- to create credential offer not bound to connectionAgent.proofs.createOutOfBandRequest
- to create presentation request not bound to connection~service
decoratorRequired more changes than initially thought because I had to remove the required
connection
parameter everywhere.Fixes #347
Fixes #346