github.com/celestiaorg/celestia-node@v0.15.0-beta.1/share/availability/light/availability_test.go (about) 1 package light 2 3 import ( 4 "context" 5 _ "embed" 6 "strconv" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 12 "github.com/celestiaorg/celestia-node/header/headertest" 13 "github.com/celestiaorg/celestia-node/share" 14 availability_test "github.com/celestiaorg/celestia-node/share/availability/test" 15 "github.com/celestiaorg/celestia-node/share/ipld" 16 "github.com/celestiaorg/celestia-node/share/sharetest" 17 ) 18 19 func TestSharesAvailableCaches(t *testing.T) { 20 ctx, cancel := context.WithCancel(context.Background()) 21 defer cancel() 22 23 getter, eh := GetterWithRandSquare(t, 16) 24 dah := eh.DAH 25 avail := TestAvailability(getter) 26 27 // cache doesn't have dah yet 28 has, err := avail.ds.Has(ctx, rootKey(dah)) 29 assert.NoError(t, err) 30 assert.False(t, has) 31 32 err = avail.SharesAvailable(ctx, eh) 33 assert.NoError(t, err) 34 35 // is now cached 36 has, err = avail.ds.Has(ctx, rootKey(dah)) 37 assert.NoError(t, err) 38 assert.True(t, has) 39 } 40 41 func TestSharesAvailableHitsCache(t *testing.T) { 42 ctx, cancel := context.WithCancel(context.Background()) 43 defer cancel() 44 45 getter, _ := GetterWithRandSquare(t, 16) 46 avail := TestAvailability(getter) 47 48 bServ := ipld.NewMemBlockservice() 49 dah := availability_test.RandFillBS(t, 16, bServ) 50 eh := headertest.RandExtendedHeaderWithRoot(t, dah) 51 52 // blockstore doesn't actually have the dah 53 err := avail.SharesAvailable(ctx, eh) 54 require.Error(t, err) 55 56 // cache doesn't have dah yet, since it errored 57 has, err := avail.ds.Has(ctx, rootKey(dah)) 58 assert.NoError(t, err) 59 assert.False(t, has) 60 61 err = avail.ds.Put(ctx, rootKey(dah), []byte{}) 62 require.NoError(t, err) 63 64 // should hit cache after putting 65 err = avail.SharesAvailable(ctx, eh) 66 require.NoError(t, err) 67 } 68 69 func TestSharesAvailableEmptyRoot(t *testing.T) { 70 ctx, cancel := context.WithCancel(context.Background()) 71 defer cancel() 72 73 getter, _ := GetterWithRandSquare(t, 16) 74 avail := TestAvailability(getter) 75 76 eh := headertest.RandExtendedHeaderWithRoot(t, share.EmptyRoot()) 77 err := avail.SharesAvailable(ctx, eh) 78 assert.NoError(t, err) 79 } 80 81 func TestSharesAvailable(t *testing.T) { 82 ctx, cancel := context.WithCancel(context.Background()) 83 defer cancel() 84 85 getter, dah := GetterWithRandSquare(t, 16) 86 avail := TestAvailability(getter) 87 err := avail.SharesAvailable(ctx, dah) 88 assert.NoError(t, err) 89 } 90 91 func TestSharesAvailableFailed(t *testing.T) { 92 ctx, cancel := context.WithCancel(context.Background()) 93 defer cancel() 94 95 bServ := ipld.NewMemBlockservice() 96 dah := availability_test.RandFillBS(t, 16, bServ) 97 eh := headertest.RandExtendedHeaderWithRoot(t, dah) 98 99 getter, _ := GetterWithRandSquare(t, 16) 100 avail := TestAvailability(getter) 101 err := avail.SharesAvailable(ctx, eh) 102 assert.Error(t, err) 103 } 104 105 func TestShareAvailableOverMocknet_Light(t *testing.T) { 106 ctx, cancel := context.WithCancel(context.Background()) 107 defer cancel() 108 109 net := availability_test.NewTestDAGNet(ctx, t) 110 _, root := RandNode(net, 16) 111 eh := headertest.RandExtendedHeader(t) 112 eh.DAH = root 113 nd := Node(net) 114 net.ConnectAll() 115 116 err := nd.SharesAvailable(ctx, eh) 117 assert.NoError(t, err) 118 } 119 120 func TestGetShare(t *testing.T) { 121 ctx, cancel := context.WithCancel(context.Background()) 122 defer cancel() 123 124 n := 16 125 getter, eh := GetterWithRandSquare(t, n) 126 127 for i := range make([]bool, n) { 128 for j := range make([]bool, n) { 129 sh, err := getter.GetShare(ctx, eh, i, j) 130 assert.NotNil(t, sh) 131 assert.NoError(t, err) 132 } 133 } 134 } 135 136 func TestService_GetSharesByNamespace(t *testing.T) { 137 var tests = []struct { 138 squareSize int 139 expectedShareCount int 140 }{ 141 {squareSize: 4, expectedShareCount: 2}, 142 {squareSize: 16, expectedShareCount: 2}, 143 {squareSize: 128, expectedShareCount: 2}, 144 } 145 146 for _, tt := range tests { 147 t.Run("size: "+strconv.Itoa(tt.squareSize), func(t *testing.T) { 148 getter, bServ := EmptyGetter() 149 totalShares := tt.squareSize * tt.squareSize 150 randShares := sharetest.RandShares(t, totalShares) 151 idx1 := (totalShares - 1) / 2 152 idx2 := totalShares / 2 153 if tt.expectedShareCount > 1 { 154 // make it so that two rows have the same namespace 155 copy(share.GetNamespace(randShares[idx2]), share.GetNamespace(randShares[idx1])) 156 } 157 root := availability_test.FillBS(t, bServ, randShares) 158 eh := headertest.RandExtendedHeader(t) 159 eh.DAH = root 160 randNamespace := share.GetNamespace(randShares[idx1]) 161 162 shares, err := getter.GetSharesByNamespace(context.Background(), eh, randNamespace) 163 require.NoError(t, err) 164 require.NoError(t, shares.Verify(root, randNamespace)) 165 flattened := shares.Flatten() 166 assert.Len(t, flattened, tt.expectedShareCount) 167 for _, value := range flattened { 168 assert.Equal(t, randNamespace, share.GetNamespace(value)) 169 } 170 if tt.expectedShareCount > 1 { 171 // idx1 is always smaller than idx2 172 assert.Equal(t, randShares[idx1], flattened[0]) 173 assert.Equal(t, randShares[idx2], flattened[1]) 174 } 175 }) 176 t.Run("last two rows of a 4x4 square that have the same namespace have valid NMT proofs", func(t *testing.T) { 177 squareSize := 4 178 totalShares := squareSize * squareSize 179 getter, bServ := EmptyGetter() 180 randShares := sharetest.RandShares(t, totalShares) 181 lastNID := share.GetNamespace(randShares[totalShares-1]) 182 for i := totalShares / 2; i < totalShares; i++ { 183 copy(share.GetNamespace(randShares[i]), lastNID) 184 } 185 root := availability_test.FillBS(t, bServ, randShares) 186 eh := headertest.RandExtendedHeader(t) 187 eh.DAH = root 188 189 shares, err := getter.GetSharesByNamespace(context.Background(), eh, lastNID) 190 require.NoError(t, err) 191 require.NoError(t, shares.Verify(root, lastNID)) 192 }) 193 } 194 } 195 196 func TestGetShares(t *testing.T) { 197 ctx, cancel := context.WithCancel(context.Background()) 198 defer cancel() 199 200 n := 16 201 getter, eh := GetterWithRandSquare(t, n) 202 203 eds, err := getter.GetEDS(ctx, eh) 204 require.NoError(t, err) 205 gotDAH, err := share.NewRoot(eds) 206 require.NoError(t, err) 207 208 require.True(t, eh.DAH.Equals(gotDAH)) 209 } 210 211 func TestService_GetSharesByNamespaceNotFound(t *testing.T) { 212 getter, eh := GetterWithRandSquare(t, 1) 213 eh.DAH.RowRoots = nil 214 215 emptyShares, err := getter.GetSharesByNamespace(context.Background(), eh, sharetest.RandV0Namespace()) 216 require.NoError(t, err) 217 require.Empty(t, emptyShares.Flatten()) 218 } 219 220 func BenchmarkService_GetSharesByNamespace(b *testing.B) { 221 var tests = []struct { 222 amountShares int 223 }{ 224 {amountShares: 4}, 225 {amountShares: 16}, 226 {amountShares: 128}, 227 } 228 229 for _, tt := range tests { 230 b.Run(strconv.Itoa(tt.amountShares), func(b *testing.B) { 231 t := &testing.T{} 232 getter, eh := GetterWithRandSquare(t, tt.amountShares) 233 root := eh.DAH 234 randNamespace := root.RowRoots[(len(root.RowRoots)-1)/2][:share.NamespaceSize] 235 root.RowRoots[(len(root.RowRoots) / 2)] = root.RowRoots[(len(root.RowRoots)-1)/2] 236 b.ResetTimer() 237 for i := 0; i < b.N; i++ { 238 _, err := getter.GetSharesByNamespace(context.Background(), eh, randNamespace) 239 require.NoError(t, err) 240 } 241 }) 242 } 243 }