github.com/celestiaorg/celestia-node@v0.15.0-beta.1/nodebuilder/tests/api_test.go (about)

     1  //go:build api || integration
     2  
     3  package tests
     4  
     5  import (
     6  	"context"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/filecoin-project/go-jsonrpc/auth"
    11  	"github.com/libp2p/go-libp2p/core/host"
    12  	"github.com/libp2p/go-libp2p/core/peer"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/celestiaorg/celestia-node/api/rpc/client"
    16  	"github.com/celestiaorg/celestia-node/blob"
    17  	"github.com/celestiaorg/celestia-node/blob/blobtest"
    18  	"github.com/celestiaorg/celestia-node/nodebuilder"
    19  	"github.com/celestiaorg/celestia-node/nodebuilder/node"
    20  	"github.com/celestiaorg/celestia-node/nodebuilder/tests/swamp"
    21  )
    22  
    23  const (
    24  	btime = time.Millisecond * 300
    25  )
    26  
    27  func TestNodeModule(t *testing.T) {
    28  	ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout)
    29  	t.Cleanup(cancel)
    30  
    31  	sw := swamp.NewSwamp(t, swamp.WithBlockTime(time.Second))
    32  	// start a bridge node
    33  	bridge := sw.NewBridgeNode()
    34  	err := bridge.Start(ctx)
    35  	require.NoError(t, err)
    36  
    37  	bridgeAddr := "http://" + bridge.RPCServer.ListenAddr()
    38  
    39  	writePerms := []auth.Permission{"public", "read", "write"}
    40  	adminPerms := []auth.Permission{"public", "read", "write", "admin"}
    41  	jwt, err := bridge.AdminServ.AuthNew(ctx, adminPerms)
    42  	require.NoError(t, err)
    43  
    44  	client, err := client.NewClient(ctx, bridgeAddr, jwt)
    45  	require.NoError(t, err)
    46  
    47  	info, err := client.Node.Info(ctx)
    48  	require.NoError(t, err)
    49  	require.Equal(t, info.APIVersion, node.APIVersion)
    50  
    51  	ready, err := client.Node.Ready(ctx)
    52  	require.NoError(t, err)
    53  	require.True(t, ready)
    54  
    55  	perms, err := client.Node.AuthVerify(ctx, jwt)
    56  	require.NoError(t, err)
    57  	require.Equal(t, perms, adminPerms)
    58  
    59  	writeJWT, err := client.Node.AuthNew(ctx, writePerms)
    60  	require.NoError(t, err)
    61  
    62  	perms, err = client.Node.AuthVerify(ctx, writeJWT)
    63  	require.NoError(t, err)
    64  	require.Equal(t, perms, writePerms)
    65  
    66  }
    67  
    68  func TestGetByHeight(t *testing.T) {
    69  	ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout)
    70  	t.Cleanup(cancel)
    71  
    72  	sw := swamp.NewSwamp(t, swamp.WithBlockTime(time.Second))
    73  
    74  	// start a bridge node
    75  	bridge := sw.NewBridgeNode()
    76  	err := bridge.Start(ctx)
    77  	require.NoError(t, err)
    78  
    79  	rpcClient := getAdminClient(ctx, bridge, t)
    80  
    81  	// let a few blocks be produced
    82  	_, err = rpcClient.Header.WaitForHeight(ctx, 3)
    83  	require.NoError(t, err)
    84  
    85  	networkHead, err := rpcClient.Header.NetworkHead(ctx)
    86  	require.NoError(t, err)
    87  	_, err = rpcClient.Header.GetByHeight(ctx, networkHead.Height()+1)
    88  	require.Nil(t, err, "Requesting syncer.Head()+1 shouldn't return an error")
    89  
    90  	networkHead, err = rpcClient.Header.NetworkHead(ctx)
    91  	require.NoError(t, err)
    92  	_, err = rpcClient.Header.GetByHeight(ctx, networkHead.Height()+2)
    93  	require.ErrorContains(t, err, "given height is from the future")
    94  }
    95  
    96  // TestBlobRPC ensures that blobs can be submitted via rpc
    97  func TestBlobRPC(t *testing.T) {
    98  	ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout)
    99  	t.Cleanup(cancel)
   100  
   101  	sw := swamp.NewSwamp(t, swamp.WithBlockTime(btime))
   102  
   103  	// start a bridge node
   104  	bridge := sw.NewBridgeNode()
   105  	err := bridge.Start(ctx)
   106  	require.NoError(t, err)
   107  
   108  	rpcClient := getAdminClient(ctx, bridge, t)
   109  
   110  	appBlobs, err := blobtest.GenerateV0Blobs([]int{8}, false)
   111  	require.NoError(t, err)
   112  
   113  	newBlob, err := blob.NewBlob(
   114  		appBlobs[0].ShareVersion,
   115  		append([]byte{appBlobs[0].NamespaceVersion}, appBlobs[0].NamespaceID...),
   116  		appBlobs[0].Data,
   117  	)
   118  	require.NoError(t, err)
   119  
   120  	height, err := rpcClient.Blob.Submit(ctx, []*blob.Blob{newBlob}, blob.DefaultGasPrice())
   121  	require.NoError(t, err)
   122  	require.True(t, height != 0)
   123  }
   124  
   125  // TestHeaderSubscription ensures that the header subscription over RPC works
   126  // as intended and gets canceled successfully after rpc context cancellation.
   127  func TestHeaderSubscription(t *testing.T) {
   128  	ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout)
   129  	t.Cleanup(cancel)
   130  
   131  	sw := swamp.NewSwamp(t, swamp.WithBlockTime(btime))
   132  
   133  	// start a bridge node
   134  	bridge := sw.NewBridgeNode()
   135  	err := bridge.Start(ctx)
   136  	require.NoError(t, err)
   137  
   138  	cfg := nodebuilder.DefaultConfig(node.Light)
   139  	addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host))
   140  	require.NoError(t, err)
   141  	cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String())
   142  
   143  	// start a light node that's connected to the bridge node
   144  	light := sw.NewNodeWithConfig(node.Light, cfg)
   145  	err = light.Start(ctx)
   146  	require.NoError(t, err)
   147  
   148  	lightClient := getAdminClient(ctx, light, t)
   149  
   150  	// subscribe to headers via the light node's RPC header subscription
   151  	subctx, subcancel := context.WithCancel(ctx)
   152  	sub, err := lightClient.Header.Subscribe(subctx)
   153  	require.NoError(t, err)
   154  	// listen for 5 headers
   155  	for i := 0; i < 5; i++ {
   156  		select {
   157  		case <-ctx.Done():
   158  			t.Fatal(ctx.Err())
   159  		case <-sub:
   160  		}
   161  	}
   162  	// cancel subscription via context
   163  	subcancel()
   164  
   165  	// stop the light node and expect no outstanding subscription errors
   166  	err = light.Stop(ctx)
   167  	require.NoError(t, err)
   168  }