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 }