github.com/storacha/go-ucanto@v0.7.2/core/delegation/delegation_test.go (about) 1 package delegation 2 3 import ( 4 _ "embed" 5 "fmt" 6 "slices" 7 "testing" 8 9 "github.com/storacha/go-ucanto/core/dag/blockstore" 10 "github.com/storacha/go-ucanto/core/ipld" 11 "github.com/storacha/go-ucanto/core/ipld/block" 12 "github.com/storacha/go-ucanto/testing/fixtures" 13 "github.com/storacha/go-ucanto/testing/helpers" 14 "github.com/storacha/go-ucanto/ucan" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestExport(t *testing.T) { 19 prf, err := Delegate( 20 fixtures.Alice, 21 fixtures.Bob, 22 []ucan.Capability[ucan.NoCaveats]{ 23 ucan.NewCapability("test/proof", fixtures.Alice.DID().String(), ucan.NoCaveats{}), 24 }, 25 ) 26 require.NoError(t, err) 27 dlg, err := Delegate( 28 fixtures.Bob, 29 fixtures.Mallory, 30 []ucan.Capability[ucan.NoCaveats]{ 31 ucan.NewCapability("test/proof", fixtures.Alice.DID().String(), ucan.NoCaveats{}), 32 }, 33 WithProof( 34 FromDelegation(prf), 35 // include an absent proof to prove things don't break - PUN INTENDED 36 FromLink(helpers.RandomCID()), 37 ), 38 ) 39 require.NoError(t, err) 40 41 bs, err := blockstore.NewBlockStore() 42 require.NoError(t, err) 43 44 var blks []ipld.Block 45 for b, err := range dlg.Blocks() { 46 require.NoError(t, err) 47 require.NoError(t, bs.Put(b)) 48 blks = append(blks, b) 49 } 50 require.Len(t, blks, 2) 51 require.True(t, slices.ContainsFunc(blks, func(b ipld.Block) bool { 52 return b.Link().String() == prf.Link().String() 53 })) 54 require.True(t, slices.ContainsFunc(blks, func(b ipld.Block) bool { 55 return b.Link().String() == dlg.Link().String() 56 })) 57 58 // add an additional block to the blockstore that is not linked to by the 59 // delegation 60 otherblk := block.NewBlock(helpers.RandomCID(), helpers.RandomBytes(32)) 61 err = bs.Put(otherblk) 62 require.NoError(t, err) 63 64 // reinstantiate delegation with our new blockstore 65 dlg, err = NewDelegationView(dlg.Link(), bs) 66 require.NoError(t, err) 67 68 var exblks []ipld.Block 69 // export the delegation from the blockstore 70 for b, err := range dlg.Export() { 71 require.NoError(t, err) 72 exblks = append(exblks, b) 73 } 74 75 // expect exblks to have the same blocks in the same order and it should not 76 // include otherblk 77 require.Len(t, exblks, len(blks)) 78 for i, b := range blks { 79 require.Equal(t, b.Link().String(), exblks[i].Link().String()) 80 } 81 82 // expect dlg.Blocks() to include otherblk though... 83 var blklnks []string 84 for b, err := range dlg.Blocks() { 85 require.NoError(t, err) 86 blklnks = append(blklnks, b.Link().String()) 87 } 88 require.Contains(t, blklnks, otherblk.Link().String()) 89 } 90 91 func TestExportOmitsProofs(t *testing.T) { 92 prf, err := Delegate( 93 fixtures.Alice, 94 fixtures.Bob, 95 []ucan.Capability[ucan.NoCaveats]{ 96 ucan.NewCapability("test/proof", fixtures.Alice.DID().String(), ucan.NoCaveats{}), 97 }, 98 ) 99 require.NoError(t, err) 100 dlg, err := Delegate( 101 fixtures.Bob, 102 fixtures.Mallory, 103 []ucan.Capability[ucan.NoCaveats]{ 104 ucan.NewCapability("test/proof", fixtures.Alice.DID().String(), ucan.NoCaveats{}), 105 }, 106 WithProof( 107 FromDelegation(prf), 108 // include an absent proof to prove things don't break - PUN INTENDED 109 FromLink(helpers.RandomCID()), 110 ), 111 ) 112 require.NoError(t, err) 113 114 blks := map[string]struct{}{} 115 for b, err := range dlg.Export() { 116 require.NoError(t, err) 117 blks[b.Link().String()] = struct{}{} 118 } 119 120 exblks := map[string]struct{}{} 121 // export the delegation from the blockstore, excluding the proof 122 for b, err := range dlg.Export(WithOmitProof(prf.Link())) { 123 require.NoError(t, err) 124 exblks[b.Link().String()] = struct{}{} 125 } 126 127 require.Contains(t, blks, prf.Link().String()) 128 require.NotContains(t, exblks, prf.Link().String()) 129 } 130 131 func TestAttach(t *testing.T) { 132 dlg, err := Delegate( 133 fixtures.Alice, 134 fixtures.Bob, 135 []ucan.Capability[ucan.NoCaveats]{ 136 ucan.NewCapability("test/attach", fixtures.Alice.DID().String(), ucan.NoCaveats{}), 137 }, 138 ) 139 require.NoError(t, err) 140 141 blk := block.NewBlock(helpers.RandomCID(), helpers.RandomBytes(32)) 142 err = dlg.Attach(blk) 143 require.NoError(t, err) 144 145 var blklnks []string 146 for b, err := range dlg.Blocks() { 147 require.NoError(t, err) 148 blklnks = append(blklnks, b.Link().String()) 149 } 150 require.Contains(t, blklnks, blk.Link().String()) 151 } 152 153 func TestFormatParse(t *testing.T) { 154 dlg, err := Delegate( 155 fixtures.Alice, 156 fixtures.Bob, 157 []ucan.Capability[ucan.NoCaveats]{ 158 ucan.NewCapability("test/proof", fixtures.Alice.DID().String(), ucan.NoCaveats{}), 159 }, 160 ) 161 require.NoError(t, err) 162 163 formatted, err := Format(dlg) 164 require.NoError(t, err) 165 166 fmt.Println(formatted) 167 168 parsed, err := Parse(formatted) 169 require.NoError(t, err) 170 171 require.Equal(t, dlg.Link(), parsed.Link()) 172 } 173 174 //go:embed delegationnonb.car 175 var delegationnonb []byte 176 177 // delegationnonb.car is an archived delegation with a capability with no `nb`. 178 // This is (currently) difficult to accomplish in Go, but perfectly common in 179 // JS, leading to delegations from a server which a Go client chokes on (hence 180 // this test). The delegation was generated with JS like the following: 181 182 // const client = await getClient() 183 // 184 // const delegation = await delegate({ 185 // issuer: client.agent.issuer, 186 // audience: DID.parse('did:example:alice'), 187 // capabilities: [ 188 // { 189 // with: 'did:key:123456789', 190 // can: 'do/something', 191 // }, 192 // ], 193 // }) 194 // 195 // const res = await delegation.archive() 196 // fs.writeFileSync('delegationnonb.car', res.ok) 197 198 func TestParseNoNb(t *testing.T) { 199 // An archived delegation with a capability with no `nb` 200 dlg, err := Extract(delegationnonb) 201 require.NoError(t, err) 202 require.Equal(t, "did:key:z6MkpveRpPySqSVXyhAmWbyQLdY9w5noKr1Ff2MX8P9htje9", dlg.Issuer().DID().String()) 203 require.Equal(t, "did:example:alice", dlg.Audience().DID().String()) 204 require.Len(t, dlg.Capabilities(), 1) 205 require.Equal(t, "do/something", dlg.Capabilities()[0].Can()) 206 require.Equal(t, "did:key:123456789", dlg.Capabilities()[0].With()) 207 require.Equal(t, nil, dlg.Capabilities()[0].Nb()) 208 }