toolkit/client: fix FindProof to handle self-delegation properly
This commit is contained in:
@@ -197,7 +197,7 @@ func TestToken_ExecutionAllowed(t *testing.T) {
|
|||||||
cmd: delegationtest.NominalCommand,
|
cmd: delegationtest.NominalCommand,
|
||||||
args: emptyArguments,
|
args: emptyArguments,
|
||||||
proofs: []cid.Cid{delegationtest.TokenBobBobCID},
|
proofs: []cid.Cid{delegationtest.TokenBobBobCID},
|
||||||
err: invocation.ErrBrokenChain,
|
err: invocation.ErrWrongSub,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -206,6 +206,8 @@ func TestToken_ExecutionAllowed(t *testing.T) {
|
|||||||
tkn, err := invocation.New(tc.issuer.DID(), tc.cmd, didtest.PersonaAlice.DID(), tc.proofs, tc.opts...)
|
tkn, err := invocation.New(tc.issuer.DID(), tc.cmd, didtest.PersonaAlice.DID(), tc.proofs, tc.opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Log(tkn.String())
|
||||||
|
|
||||||
err = tkn.ExecutionAllowed(delegationtest.GetDelegationLoader())
|
err = tkn.ExecutionAllowed(delegationtest.GetDelegationLoader())
|
||||||
|
|
||||||
if tc.err != nil {
|
if tc.err != nil {
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import (
|
|||||||
// Note: the returned delegation(s) don't have to match exactly the parameters, as long as they allow them.
|
// Note: the returned delegation(s) don't have to match exactly the parameters, as long as they allow them.
|
||||||
// Note: the implemented algorithm won't perform well with a large number of delegations.
|
// Note: the implemented algorithm won't perform well with a large number of delegations.
|
||||||
func FindProof(dlgs func() iter.Seq[*delegation.Bundle], issuer did.DID, cmd command.Command, subject did.DID) []cid.Cid {
|
func FindProof(dlgs func() iter.Seq[*delegation.Bundle], issuer did.DID, cmd command.Command, subject did.DID) []cid.Cid {
|
||||||
// TODO: maybe that should be part of delegation.Token directly?
|
continuePath := func(dlg *delegation.Token, issuer did.DID, cmd command.Command, subject did.DID) bool {
|
||||||
dlgMatch := func(dlg *delegation.Token, issuer did.DID, cmd command.Command, subject did.DID) bool {
|
|
||||||
// The Subject of each delegation must equal the invocation's Subject (or Audience if defined). - 4f
|
// The Subject of each delegation must equal the invocation's Subject (or Audience if defined). - 4f
|
||||||
if !dlg.Subject().Equal(subject) {
|
if !dlg.Subject().Equal(subject) {
|
||||||
return false
|
return false
|
||||||
@@ -47,7 +46,7 @@ func FindProof(dlgs func() iter.Seq[*delegation.Bundle], issuer did.DID, cmd com
|
|||||||
var candidateLeaf []*delegation.Bundle
|
var candidateLeaf []*delegation.Bundle
|
||||||
|
|
||||||
for bundle := range dlgs() {
|
for bundle := range dlgs() {
|
||||||
if !dlgMatch(bundle.Decoded, issuer, cmd, subject) {
|
if !continuePath(bundle.Decoded, issuer, cmd, subject) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
candidateLeaf = append(candidateLeaf, bundle)
|
candidateLeaf = append(candidateLeaf, bundle)
|
||||||
@@ -83,7 +82,12 @@ func FindProof(dlgs func() iter.Seq[*delegation.Bundle], issuer did.DID, cmd com
|
|||||||
|
|
||||||
// find parent delegation for our current delegation
|
// find parent delegation for our current delegation
|
||||||
for candidate := range dlgs() {
|
for candidate := range dlgs() {
|
||||||
if !dlgMatch(candidate.Decoded, at.Decoded.Issuer(), at.Decoded.Command(), subject) {
|
// Prune the delegations that don't match the current proof.
|
||||||
|
if !continuePath(candidate.Decoded, at.Decoded.Issuer(), at.Decoded.Command(), subject) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Prune the self-delegations as they can't get us closer to what we are looking for.
|
||||||
|
if candidate.Decoded.Issuer().Equal(candidate.Decoded.Audience()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import (
|
|||||||
"iter"
|
"iter"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/MetaMask/go-did-it"
|
||||||
"github.com/MetaMask/go-did-it/didtest"
|
"github.com/MetaMask/go-did-it/didtest"
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/ucan-wg/go-ucan/pkg/command"
|
"github.com/ucan-wg/go-ucan/pkg/command"
|
||||||
@@ -23,17 +25,76 @@ func TestFindProof(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(t, delegationtest.ProofAliceBob,
|
for _, tc := range []struct {
|
||||||
FindProof(dlgs, didtest.PersonaBob.DID(), delegationtest.NominalCommand, didtest.PersonaAlice.DID()))
|
name string
|
||||||
require.Equal(t, delegationtest.ProofAliceBobCarol,
|
issuer did.DID
|
||||||
FindProof(dlgs, didtest.PersonaCarol.DID(), delegationtest.NominalCommand, didtest.PersonaAlice.DID()))
|
command command.Command
|
||||||
require.Equal(t, delegationtest.ProofAliceBobCarolDan,
|
subject did.DID
|
||||||
FindProof(dlgs, didtest.PersonaDan.DID(), delegationtest.NominalCommand, didtest.PersonaAlice.DID()))
|
expected []cid.Cid
|
||||||
require.Equal(t, delegationtest.ProofAliceBobCarolDanErin,
|
}{
|
||||||
FindProof(dlgs, didtest.PersonaErin.DID(), delegationtest.NominalCommand, didtest.PersonaAlice.DID()))
|
// Passes
|
||||||
require.Equal(t, delegationtest.ProofAliceBobCarolDanErinFrank,
|
{
|
||||||
FindProof(dlgs, didtest.PersonaFrank.DID(), delegationtest.NominalCommand, didtest.PersonaAlice.DID()))
|
name: "Alice --> Alice (self-delegation)",
|
||||||
|
issuer: didtest.PersonaAlice.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: []cid.Cid{delegationtest.TokenAliceAliceCID},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Alice --> Bob",
|
||||||
|
issuer: didtest.PersonaBob.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: delegationtest.ProofAliceBob,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Alice --> Bob --> Carol",
|
||||||
|
issuer: didtest.PersonaCarol.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: delegationtest.ProofAliceBobCarol,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Alice --> Bob --> Carol --> Dan",
|
||||||
|
issuer: didtest.PersonaDan.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: delegationtest.ProofAliceBobCarolDan,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Alice --> Bob --> Carol --> Dan --> Erin",
|
||||||
|
issuer: didtest.PersonaErin.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: delegationtest.ProofAliceBobCarolDanErin,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Alice --> Bob --> Carol --> Dan --> Erin --> Frank",
|
||||||
|
issuer: didtest.PersonaFrank.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: delegationtest.ProofAliceBobCarolDanErinFrank,
|
||||||
|
},
|
||||||
|
|
||||||
// wrong command
|
// Fails
|
||||||
require.Empty(t, FindProof(dlgs, didtest.PersonaBob.DID(), command.New("foo"), didtest.PersonaAlice.DID()))
|
{
|
||||||
|
name: "wrong command",
|
||||||
|
issuer: didtest.PersonaBob.DID(),
|
||||||
|
command: command.New("foo"),
|
||||||
|
subject: didtest.PersonaAlice.DID(),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wrong subject",
|
||||||
|
issuer: didtest.PersonaBob.DID(),
|
||||||
|
command: delegationtest.NominalCommand,
|
||||||
|
subject: didtest.PersonaDan.DID(),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
res := FindProof(dlgs, tc.issuer, tc.command, tc.subject)
|
||||||
|
require.Equal(t, tc.expected, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user