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  }