From 87ae5d00425ec3bfee9ede40b0104884fa4c81ec Mon Sep 17 00:00:00 2001 From: rene <41963722+renaynay@users.noreply.github.com> Date: Sat, 22 Apr 2023 09:28:07 +0200 Subject: [PATCH] chore: clean up sync_test tests --- nodebuilder/tests/fraud_test.go | 32 ++-- nodebuilder/tests/sync_test.go | 317 +++++++++++++++----------------- 2 files changed, 172 insertions(+), 177 deletions(-) diff --git a/nodebuilder/tests/fraud_test.go b/nodebuilder/tests/fraud_test.go index ac6858d1f9..b8e609b663 100644 --- a/nodebuilder/tests/fraud_test.go +++ b/nodebuilder/tests/fraud_test.go @@ -33,16 +33,18 @@ Note: 15 is not available because DASer will be stopped before reaching this hei Another note: this test disables share exchange to speed up test results. */ func TestFraudProofBroadcasting(t *testing.T) { - const ( - blocks = 15 - bsize = 2 - btime = time.Millisecond * 300 - ) - sw := swamp.NewSwamp(t, swamp.WithBlockTime(btime)) ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout) t.Cleanup(cancel) - fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, blocks) + const ( + blocks = 15 + blockSize = 2 + blockTime = time.Millisecond * 300 + ) + + sw := swamp.NewSwamp(t, swamp.WithBlockTime(blockTime)) + fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, blockSize, blocks) + cfg := nodebuilder.DefaultConfig(node.Bridge) cfg.Share.UseShareExchange = false bridge := sw.NewNodeWithConfig( @@ -53,12 +55,13 @@ func TestFraudProofBroadcasting(t *testing.T) { err := bridge.Start(ctx) require.NoError(t, err) - addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) - require.NoError(t, err) cfg = nodebuilder.DefaultConfig(node.Full) cfg.Share.UseShareExchange = false + addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) + require.NoError(t, err) cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) + store := nodebuilder.MockStore(t, cfg) full := sw.NewNodeWithStore(node.Full, store) @@ -70,14 +73,17 @@ func TestFraudProofBroadcasting(t *testing.T) { subscr, err := full.FraudServ.Subscribe(ctx, byzantine.BadEncoding) require.NoError(t, err) - p := <-subscr - require.Equal(t, 10, int(p.Height())) - + select { + case p := <-subscr: + require.Equal(t, 10, int(p.Height())) + case <-ctx.Done(): + t.Fatal("fraud proof was not received in time") + } // This is an obscure way to check if the Syncer was stopped. // If we cannot get a height header within a timeframe it means the syncer was stopped // FIXME: Eventually, this should be a check on service registry managing and keeping // lifecycles of each Module. - syncCtx, syncCancel := context.WithTimeout(context.Background(), btime) + syncCtx, syncCancel := context.WithTimeout(context.Background(), blockTime) _, err = full.HeaderServ.GetByHeight(syncCtx, 100) require.ErrorIs(t, err, context.DeadlineExceeded) syncCancel() diff --git a/nodebuilder/tests/sync_test.go b/nodebuilder/tests/sync_test.go index adaf788884..54ac9cba19 100644 --- a/nodebuilder/tests/sync_test.go +++ b/nodebuilder/tests/sync_test.go @@ -17,60 +17,99 @@ import ( // Common consts for tests producing filled blocks const ( - blocks = 20 - bsize = 16 - btime = time.Millisecond * 300 + numBlocks = 20 + bsize = 16 + btime = time.Millisecond * 300 ) /* -Test-Case: Sync a Light Node with a Bridge Node(includes DASing of non-empty blocks) +Test-Case: Header and block/sample sync against a Bridge Node of non-empty blocks. + Steps: 1. Create a Bridge Node(BN) 2. Start a BN 3. Check BN is synced to height 20 -4. Create a Light Node(LN) with a trusted peer + +Light node: +4. Create a Light Node (LN) with bridge as a trusted peer 5. Start a LN with a defined connection to the BN -6. Check LN is synced to height 30 +6. Check LN is header-synced to height 20 +7. Wait until LN has sampled height 20 +8. Wait for LN DASer to catch up to network head + +Full node: +4. Create a Full Node (FN) with bridge as a trusted peer +5. Start a FN with a defined connection to the BN +6. Check FN is header-synced to height 20 +7. Wait until FN has synced block at height 20 +8. Wait for FN DASer to catch up to network head */ -func TestSyncLightWithBridge(t *testing.T) { +func TestSyncAgainstBridge(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout) t.Cleanup(cancel) sw := swamp.NewSwamp(t, swamp.WithBlockTime(btime)) - fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, blocks) + // wait for core network to fill 20 blocks + fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, numBlocks) + sw.WaitTillHeight(ctx, numBlocks) + // start a bridge and wait for it to sync to 20 bridge := sw.NewBridgeNode() - - sw.WaitTillHeight(ctx, 20) - err := bridge.Start(ctx) require.NoError(t, err) - - h, err := bridge.HeaderServ.GetByHeight(ctx, 20) - require.NoError(t, err) - - require.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 20)) - - addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) - require.NoError(t, err) - - cfg := nodebuilder.DefaultConfig(node.Light) - cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) - light := sw.NewNodeWithConfig(node.Light, cfg) - - err = light.Start(ctx) - require.NoError(t, err) - - h, err = light.HeaderServ.GetByHeight(ctx, 30) - require.NoError(t, err) - - err = light.ShareServ.SharesAvailable(ctx, h.DAH) - assert.NoError(t, err) - - err = light.DASer.WaitCatchUp(ctx) + h, err := bridge.HeaderServ.GetByHeight(ctx, numBlocks) require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 30)) + require.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, numBlocks)) + + t.Run("light sync against bridge", func(t *testing.T) { + // create a light node that is connected to the bridge node as + // a bootstrapper + cfg := nodebuilder.DefaultConfig(node.Light) + addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) + require.NoError(t, err) + cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) + light := sw.NewNodeWithConfig(node.Light, cfg) + // start light node and wait for it to sync 20 blocks + err = light.Start(ctx) + require.NoError(t, err) + h, err = light.HeaderServ.GetByHeight(ctx, numBlocks) + require.NoError(t, err) + assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, numBlocks)) + + // check that the light node has also sampled over the block at height 20 + err = light.ShareServ.SharesAvailable(ctx, h.DAH) + assert.NoError(t, err) + + // wait until the entire chain (up to network head) has been sampled + err = light.DASer.WaitCatchUp(ctx) + require.NoError(t, err) + }) + + t.Run("full sync against bridge", func(t *testing.T) { + // create a full node with bridge node as its bootstrapper + cfg := nodebuilder.DefaultConfig(node.Full) + addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) + require.NoError(t, err) + cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) + full := sw.NewNodeWithConfig(node.Full, cfg) + + // let full node sync 20 blocks + err = full.Start(ctx) + require.NoError(t, err) + h, err = full.HeaderServ.GetByHeight(ctx, numBlocks) + require.NoError(t, err) + assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, numBlocks)) + + // check to ensure the full node can sync the 20th block's data + err = full.ShareServ.SharesAvailable(ctx, h.DAH) + assert.NoError(t, err) + + // wait for full node to sync up the blocks from genesis -> network head. + err = full.DASer.WaitCatchUp(ctx) + require.NoError(t, err) + }) + + // wait for the core block filling process to exit require.NoError(t, <-fillDn) } @@ -85,106 +124,55 @@ Steps: 3. Check BN is synced to height 20 4. Create a Light Node(LN) with a trusted peer 5. Start a LN with a defined connection to the BN -6. Check LN is synced to height 30 -7. Stop LN -8. Start LN +6. Check LN is synced to height 20 +7. Disconnect LN from BN for 3 seconds while BN continues broadcasting new blocks from core +8. Re-connect LN and let it sync up again 9. Check LN is synced to height 40 */ func TestSyncStartStopLightWithBridge(t *testing.T) { - sw := swamp.NewSwamp(t) - - bridge := sw.NewBridgeNode() - ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout) - t.Cleanup(cancel) + defer cancel() - sw.WaitTillHeight(ctx, 50) + sw := swamp.NewSwamp(t) + // wait for core network to fill 20 blocks + fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, numBlocks) + sw.WaitTillHeight(ctx, numBlocks) + // create bridge + bridge := sw.NewBridgeNode() + // and let bridge node sync up with core network err := bridge.Start(ctx) require.NoError(t, err) - - h, err := bridge.HeaderServ.GetByHeight(ctx, 20) + h, err := bridge.HeaderServ.GetByHeight(ctx, numBlocks) require.NoError(t, err) + require.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, numBlocks)) - require.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 20)) - + // create a light node and connect it to the bridge node as a bootstrapper + cfg := nodebuilder.DefaultConfig(node.Light) addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) require.NoError(t, err) - - cfg := nodebuilder.DefaultConfig(node.Light) cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) light := sw.NewNodeWithConfig(node.Light, cfg) - require.NoError(t, light.Start(ctx)) - h, err = light.HeaderServ.GetByHeight(ctx, 30) + // start light node and let it sync to 20 + err = light.Start(ctx) require.NoError(t, err) + h, err = light.HeaderServ.GetByHeight(ctx, numBlocks) + require.NoError(t, err) + require.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, numBlocks)) - require.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 30)) - - require.NoError(t, light.Stop(ctx)) - require.NoError(t, sw.RemoveNode(light, node.Light)) - - cfg = nodebuilder.DefaultConfig(node.Light) - cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) - light = sw.NewNodeWithConfig(node.Light, cfg) - require.NoError(t, light.Start(ctx)) + // disconnect light from bridge node to force light node to miss a few blocks + sw.Disconnect(t, bridge.Host.ID(), light.Host.ID()) + time.Sleep(time.Second * 3) + sw.Connect(t, bridge.Host.ID(), light.Host.ID()) + // ensure when light node comes back up, it can sync the remainder of the chain it + // missed while sleeping h, err = light.HeaderServ.GetByHeight(ctx, 40) require.NoError(t, err) - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 40)) -} - -/* -Test-Case: Sync a Full Node with a Bridge Node(includes DASing of non-empty blocks) -Steps: -1. Create a Bridge Node(BN) -2. Start a BN -3. Check BN is synced to height 20 -4. Create a Full Node(FN) with a connection to BN as a trusted peer -5. Start a FN -6. Check FN is synced to height 30 -*/ -func TestSyncFullWithBridge(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout) - t.Cleanup(cancel) - - sw := swamp.NewSwamp(t, swamp.WithBlockTime(btime)) - fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, blocks) - - bridge := sw.NewBridgeNode() - sw.WaitTillHeight(ctx, 20) - - err := bridge.Start(ctx) - require.NoError(t, err) - - h, err := bridge.HeaderServ.GetByHeight(ctx, 20) - require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 20)) - - addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) - require.NoError(t, err) - - cfg := nodebuilder.DefaultConfig(node.Full) - cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) - cfg.Share.UseShareExchange = false - full := sw.NewNodeWithConfig(node.Full, cfg) - require.NoError(t, full.Start(ctx)) - - h, err = full.HeaderServ.GetByHeight(ctx, 30) - require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 30)) - - err = full.ShareServ.SharesAvailable(ctx, h.DAH) - assert.NoError(t, err) - - err = full.DASer.WaitCatchUp(ctx) - require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 30)) + // wait for the core block filling process to exit require.NoError(t, <-fillDn) } @@ -199,59 +187,62 @@ Steps: 3. Check BN is synced to height 20 4. Create a Full Node(FN) with a connection to BN as a trusted peer 5. Start a FN -6. Check FN is synced to height 30 +6. Check FN is synced to network head 7. Create a Light Node(LN) with a connection to FN as a trusted peer -8. Start LN -9. Check LN is synced to height 50 +8. Ensure LN is NOT connected to BN and only connected to FN +9. Start LN +10. Check LN is synced to network head */ -func TestSyncLightWithFull(t *testing.T) { - sw := swamp.NewSwamp(t) - - bridge := sw.NewBridgeNode() - +func TestSyncLightAgainstFull(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout) t.Cleanup(cancel) - sw.WaitTillHeight(ctx, 20) + sw := swamp.NewSwamp(t) + // wait for the core network to fill up 20 blocks + fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, numBlocks) + sw.WaitTillHeight(ctx, numBlocks) + // start a bridge node and wait for it to sync up 20 blocks + bridge := sw.NewBridgeNode() err := bridge.Start(ctx) require.NoError(t, err) - - h, err := bridge.HeaderServ.GetByHeight(ctx, 20) + h, err := bridge.HeaderServ.GetByHeight(ctx, numBlocks) require.NoError(t, err) + assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, numBlocks)) - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 20)) - + // create a FN with BN as a trusted peer + cfg := nodebuilder.DefaultConfig(node.Full) addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) require.NoError(t, err) - - cfg := nodebuilder.DefaultConfig(node.Full) cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) full := sw.NewNodeWithConfig(node.Full, cfg) - require.NoError(t, full.Start(ctx)) - h, err = full.HeaderServ.GetByHeight(ctx, 30) + // start FN and wait for it to sync up to BN + err = full.Start(ctx) require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 30)) - - addrs, err = peer.AddrInfoToP2pAddrs(host.InfoFromHost(full.Host)) + err = full.HeaderServ.SyncWait(ctx) require.NoError(t, err) + // create an LN with FN as a trusted peer cfg = nodebuilder.DefaultConfig(node.Light) + addrs, err = peer.AddrInfoToP2pAddrs(host.InfoFromHost(full.Host)) + require.NoError(t, err) cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) light := sw.NewNodeWithConfig(node.Light, cfg) + // ensure there is no direct connection between LN and BN so that + // LN relies only on FN for syncing err = sw.Network.UnlinkPeers(bridge.Host.ID(), light.Host.ID()) require.NoError(t, err) + // start LN and wait for it to sync up to network head against the FN err = light.Start(ctx) require.NoError(t, err) - - h, err = light.HeaderServ.GetByHeight(ctx, 50) + err = light.HeaderServ.SyncWait(ctx) require.NoError(t, err) - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 50)) + // wait for the core block filling process to exit + require.NoError(t, <-fillDn) } /* @@ -265,54 +256,52 @@ Steps: 3. Check BN is synced to height 20 4. Create a Full Node(FN) with a connection to BN as a trusted peer 5. Start a FN -6. Check FN is synced to height 30 -7. Create a Light Node(LN) with a connection to BN, FN as trusted peers +6. Check FN is synced to network head +7. Create a Light Node(LN) with a connection to BN and FN as trusted peers 8. Start LN -9. Check LN is synced to height 50 +9. Check LN is synced to network head. */ func TestSyncLightWithTrustedPeers(t *testing.T) { - sw := swamp.NewSwamp(t) - - bridge := sw.NewBridgeNode() - ctx, cancel := context.WithTimeout(context.Background(), swamp.DefaultTestTimeout) t.Cleanup(cancel) - sw.WaitTillHeight(ctx, 20) + sw := swamp.NewSwamp(t) + fillDn := swamp.FillBlocks(ctx, sw.ClientContext, sw.Accounts, bsize, numBlocks) + sw.WaitTillHeight(ctx, numBlocks) + // create a BN and let it sync to network head + bridge := sw.NewBridgeNode() err := bridge.Start(ctx) require.NoError(t, err) - - h, err := bridge.HeaderServ.GetByHeight(ctx, 20) - require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 20)) - - addrs, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) + err = bridge.HeaderServ.SyncWait(ctx) require.NoError(t, err) + // create a FN with BN as trusted peer cfg := nodebuilder.DefaultConfig(node.Full) - cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) + bridgeInfo, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(bridge.Host)) + require.NoError(t, err) + cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, bridgeInfo[0].String()) full := sw.NewNodeWithConfig(node.Full, cfg) - require.NoError(t, full.Start(ctx)) - h, err = full.HeaderServ.GetByHeight(ctx, 30) + // let FN sync to network head + err = full.Start(ctx) require.NoError(t, err) - - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 30)) - - addrs, err = peer.AddrInfoToP2pAddrs(host.InfoFromHost(full.Host)) + err = full.HeaderServ.SyncWait(ctx) require.NoError(t, err) + // create a LN with both FN and BN as trusted peers cfg = nodebuilder.DefaultConfig(node.Light) - cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, addrs[0].String()) + fullInfo, err := peer.AddrInfoToP2pAddrs(host.InfoFromHost(full.Host)) + require.NoError(t, err) + cfg.Header.TrustedPeers = append(cfg.Header.TrustedPeers, bridgeInfo[0].String(), fullInfo[0].String()) light := sw.NewNodeWithConfig(node.Light, cfg) + // let LN sync to network head err = light.Start(ctx) require.NoError(t, err) - - h, err = light.HeaderServ.GetByHeight(ctx, 50) + err = light.HeaderServ.SyncWait(ctx) require.NoError(t, err) - assert.EqualValues(t, h.Commit.BlockID.Hash, sw.GetCoreBlockHashByHeight(ctx, 50)) + // wait for the core block filling process to exit + require.NoError(t, <-fillDn) }