github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/consensus/synchronize_test.go (about)

     1  package consensus
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"path/filepath"
     9  	"strconv"
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/NebulousLabs/Sia/build"
    15  	"github.com/NebulousLabs/Sia/crypto"
    16  	"github.com/NebulousLabs/Sia/encoding"
    17  	"github.com/NebulousLabs/Sia/modules"
    18  	"github.com/NebulousLabs/Sia/modules/gateway"
    19  	"github.com/NebulousLabs/Sia/types"
    20  
    21  	"github.com/NebulousLabs/bolt"
    22  )
    23  
    24  // TestSynchronize tests that the consensus set can successfully synchronize
    25  // to a peer.
    26  func TestSynchronize(t *testing.T) {
    27  	if testing.Short() {
    28  		t.SkipNow()
    29  	}
    30  
    31  	cst1, err := createConsensusSetTester("TestSynchronize1")
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  	defer cst1.Close()
    36  	cst2, err := createConsensusSetTester("TestSynchronize2")
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	defer cst2.Close()
    41  
    42  	// mine on cst2 until it is above cst1
    43  	for cst1.cs.dbBlockHeight() >= cst2.cs.dbBlockHeight() {
    44  		b, _ := cst2.miner.FindBlock()
    45  		err = cst2.cs.AcceptBlock(b)
    46  		if err != nil {
    47  			t.Fatal(err)
    48  		}
    49  	}
    50  
    51  	// connect gateways, triggering a Synchronize
    52  	err = cst1.gateway.Connect(cst2.gateway.Address())
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	// blockchains should now match
    58  	for cst1.cs.dbCurrentBlockID() != cst2.cs.dbCurrentBlockID() {
    59  		time.Sleep(10 * time.Millisecond)
    60  	}
    61  
    62  	// Mine on cst2 until it is more than 'MaxCatchUpBlocks' ahead of cst2.
    63  	// NOTE: we have to disconnect prior to this, otherwise cst2 will relay
    64  	// blocks to cst1.
    65  	err = cst1.gateway.Disconnect(cst2.gateway.Address())
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	// TODO: more than 30 causes a race condition!
    70  	for cst2.cs.dbBlockHeight() < cst1.cs.dbBlockHeight()+20 {
    71  		b, _ := cst2.miner.FindBlock()
    72  		err = cst2.cs.AcceptBlock(b)
    73  		if err != nil {
    74  			t.Fatal(err)
    75  		}
    76  	}
    77  	// reconnect
    78  	err = cst1.gateway.Connect(cst2.gateway.Address())
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	// block heights should now match
    84  	for cst1.cs.dbBlockHeight() != cst2.cs.dbBlockHeight() {
    85  		time.Sleep(250 * time.Millisecond)
    86  	}
    87  
    88  	/*
    89  		// extend cst2 with a "bad" (old) block, and synchronize. cst1 should
    90  		// reject the bad block.
    91  		lockID := cst2.cs.mu.Lock()
    92  		cst2.cs.db.pushPath(cst2.cs.db.getPath(0))
    93  		cst2.cs.mu.Unlock(lockID)
    94  		if cst1.cs.db.pathHeight() == cst2.cs.db.pathHeight() {
    95  			t.Fatal("cst1 did not reject bad block")
    96  		}
    97  	*/
    98  }
    99  
   100  func TestResynchronize(t *testing.T) {
   101  	t.Skip("takes way too long")
   102  
   103  	cst1, err := createConsensusSetTester("TestResynchronize1")
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	defer cst1.Close()
   108  	cst2, err := createConsensusSetTester("TestResynchronize2")
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  	defer cst2.Close()
   113  
   114  	// TODO: without this extra block, sync fails. Why?
   115  	b, _ := cst2.miner.FindBlock()
   116  	err = cst2.cs.AcceptBlock(b)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  
   121  	// connect and disconnect, so that cst1 and cst2 are synchronized
   122  	err = cst1.gateway.Connect(cst2.gateway.Address())
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	err = cst1.gateway.Disconnect(cst2.gateway.Address())
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  
   131  	if cst1.cs.dbCurrentBlockID() != cst2.cs.dbCurrentBlockID() {
   132  		t.Fatal("Consensus Sets did not synchronize")
   133  	}
   134  
   135  	// mine a block on cst2, but hide it from cst1 during reconnect
   136  	/*
   137  		b, _ = cst2.miner.FindBlock()
   138  		err = cst2.cs.AcceptBlock(b)
   139  		if err != nil {
   140  			t.Fatal(err)
   141  		}
   142  		lockID := cst2.cs.mu.Lock()
   143  		id := cst2.cs.currentBlockID()
   144  		err = cst2.cs.db.popPath()
   145  		if err != nil {
   146  			t.Fatal(err)
   147  		}
   148  		cst2.cs.mu.Unlock(lockID)
   149  
   150  		err = cst1.gateway.Connect(cst2.gateway.Address())
   151  		if err != nil {
   152  			t.Fatal(err)
   153  		}
   154  
   155  		// add id back to cst2's current path
   156  		lockID = cst2.cs.mu.Lock()
   157  		err = cst2.cs.db.pushPath(id)
   158  		if err != nil {
   159  			t.Fatal(err)
   160  		}
   161  		cst2.cs.mu.Unlock(lockID)
   162  
   163  		// cst1 should not have the block
   164  		if cst1.cs.dbBlockHeight() == cst2.cs.dbBlockHeight() {
   165  			t.Fatal("Consensus Sets should not have the same height")
   166  		}
   167  	*/
   168  }
   169  
   170  // TestBlockHistory tests that blockHistory returns the expected sequence of
   171  // block IDs.
   172  func TestBlockHistory(t *testing.T) {
   173  	if testing.Short() {
   174  		t.SkipNow()
   175  	}
   176  
   177  	cst, err := createConsensusSetTester("TestBlockHistory")
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  	defer cst.Close()
   182  
   183  	// mine until we have enough blocks to test blockHistory
   184  	for cst.cs.dbBlockHeight() < 50 {
   185  		b, _ := cst.miner.FindBlock()
   186  		err = cst.cs.AcceptBlock(b)
   187  		if err != nil {
   188  			t.Fatal(err)
   189  		}
   190  	}
   191  
   192  	var history [32]types.BlockID
   193  	_ = cst.cs.db.View(func(tx *bolt.Tx) error {
   194  		history = blockHistory(tx)
   195  		return nil
   196  	})
   197  
   198  	// validate history
   199  	cst.cs.mu.Lock()
   200  	// first 10 IDs are linear
   201  	for i := types.BlockHeight(0); i < 10; i++ {
   202  		id, err := cst.cs.dbGetPath(cst.cs.dbBlockHeight() - i)
   203  		if err != nil {
   204  			t.Fatal(err)
   205  		}
   206  		if history[i] != id {
   207  			t.Errorf("Wrong ID in history: expected %v, got %v", id, history[i])
   208  		}
   209  	}
   210  	// next 4 IDs are exponential
   211  	heights := []types.BlockHeight{11, 15, 23, 39}
   212  	for i, height := range heights {
   213  		id, err := cst.cs.dbGetPath(cst.cs.dbBlockHeight() - height)
   214  		if err != nil {
   215  			t.Fatal(err)
   216  		}
   217  		if history[10+i] != id {
   218  			t.Errorf("Wrong ID in history: expected %v, got %v", height, history[10+i])
   219  		}
   220  	}
   221  	// finally, the genesis ID
   222  	genesisID, err := cst.cs.dbGetPath(0)
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	if history[31] != genesisID {
   227  		t.Errorf("Wrong ID in history: expected %v, got %v", genesisID, history[31])
   228  	}
   229  
   230  	cst.cs.mu.Unlock()
   231  
   232  	// remaining IDs should be empty
   233  	var emptyID types.BlockID
   234  	for i, id := range history[14:31] {
   235  		if id != emptyID {
   236  			t.Errorf("Expected empty ID at index %v, got %v", i+17, id)
   237  		}
   238  	}
   239  }
   240  
   241  // mockGatewayCountBroadcasts implements modules.Gateway to mock the Broadcast
   242  // method.
   243  type mockGatewayCountBroadcasts struct {
   244  	modules.Gateway
   245  	numBroadcasts int
   246  	mu            sync.RWMutex
   247  }
   248  
   249  // Broadcast is a mock implementation of modules.Gateway.Broadcast that
   250  // increments a counter denoting the number of times it's been called.
   251  func (g *mockGatewayCountBroadcasts) Broadcast(name string, obj interface{}, peers []modules.Peer) {
   252  	g.mu.Lock()
   253  	g.numBroadcasts++
   254  	g.mu.Unlock()
   255  	g.Gateway.Broadcast(name, obj, peers)
   256  }
   257  
   258  // TestSendBlocksBroadcastsOnce tests that the SendBlocks RPC call only
   259  // Broadcasts one block, no matter how many blocks are sent. In the case 0
   260  // blocks are sent, tests that Broadcast is never called.
   261  func TestSendBlocksBroadcastsOnce(t *testing.T) {
   262  	if testing.Short() {
   263  		t.SkipNow()
   264  	}
   265  
   266  	// Setup consensus sets.
   267  	cst1, err := blankConsensusSetTester("TestSendBlocksBroadcastsOnce1")
   268  	if err != nil {
   269  		t.Fatal(err)
   270  	}
   271  	defer cst1.Close()
   272  	cst2, err := blankConsensusSetTester("TestSendBlocksBroadcastsOnce2")
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	defer cst2.Close()
   277  	// Setup mock gateway.
   278  	mg := mockGatewayCountBroadcasts{Gateway: cst1.cs.gateway}
   279  	cst1.cs.gateway = &mg
   280  	err = cst1.cs.gateway.Connect(cst2.cs.gateway.Address())
   281  	if err != nil {
   282  		t.Fatal(err)
   283  	}
   284  
   285  	tests := []struct {
   286  		blocksToMine          int
   287  		expectedNumBroadcasts int
   288  		synced                bool
   289  	}{
   290  		// Test that no blocks are broadcast during IBD.
   291  		{
   292  			blocksToMine:          0,
   293  			expectedNumBroadcasts: 0,
   294  			synced:                false,
   295  		},
   296  		{
   297  			blocksToMine:          1,
   298  			expectedNumBroadcasts: 0,
   299  			synced:                false,
   300  		},
   301  		{
   302  			blocksToMine:          2,
   303  			expectedNumBroadcasts: 0,
   304  			synced:                false,
   305  		},
   306  		// Test that only one blocks is broadcast when IBD is done.
   307  		{
   308  			blocksToMine:          0,
   309  			expectedNumBroadcasts: 0,
   310  			synced:                true,
   311  		},
   312  		{
   313  			blocksToMine:          1,
   314  			expectedNumBroadcasts: 2,
   315  			synced:                true,
   316  		},
   317  		{
   318  			blocksToMine:          2,
   319  			expectedNumBroadcasts: 2,
   320  			synced:                true,
   321  		},
   322  		{
   323  			blocksToMine:          int(MaxCatchUpBlocks),
   324  			expectedNumBroadcasts: 2,
   325  			synced:                true,
   326  		},
   327  		{
   328  			blocksToMine:          2 * int(MaxCatchUpBlocks),
   329  			expectedNumBroadcasts: 2,
   330  			synced:                true,
   331  		},
   332  		{
   333  			blocksToMine:          2*int(MaxCatchUpBlocks) + 1,
   334  			expectedNumBroadcasts: 2,
   335  			synced:                true,
   336  		},
   337  	}
   338  	for _, test := range tests {
   339  		cst1.cs.mu.Lock()
   340  		cst1.cs.synced = test.synced
   341  		cst1.cs.mu.Unlock()
   342  		mg.mu.Lock()
   343  		mg.numBroadcasts = 0
   344  		mg.mu.Unlock()
   345  		for i := 0; i < test.blocksToMine; i++ {
   346  			b, minerErr := cst2.miner.FindBlock()
   347  			if minerErr != nil {
   348  				t.Fatal(minerErr)
   349  			}
   350  			// managedAcceptBlock is used here instead of AcceptBlock so as not to
   351  			// call Broadcast outside of the SendBlocks RPC.
   352  			err = cst2.cs.managedAcceptBlock(b)
   353  			if err != nil {
   354  				t.Fatal(err)
   355  			}
   356  		}
   357  		err = cst1.cs.gateway.RPC(cst2.cs.gateway.Address(), "SendBlocks", cst1.cs.threadedReceiveBlocks)
   358  		if err != nil {
   359  			t.Fatal(err)
   360  		}
   361  		// Sleep to wait for possible calls to Broadcast to complete. We cannot
   362  		// wait on a channel because we don't know how many times broadcast has
   363  		// been called.
   364  		time.Sleep(10 * time.Millisecond)
   365  		mg.mu.RLock()
   366  		numBroadcasts := mg.numBroadcasts
   367  		mg.mu.RUnlock()
   368  		if numBroadcasts != test.expectedNumBroadcasts {
   369  			t.Errorf("expected %d number of broadcasts, got %d", test.expectedNumBroadcasts, numBroadcasts)
   370  		}
   371  	}
   372  }
   373  
   374  // TestIntegrationRPCSendBlocks tests that the SendBlocks RPC adds blocks to
   375  // the consensus set, and that the consensus set catches with the remote peer
   376  // and possibly reorgs.
   377  func TestIntegrationRPCSendBlocks(t *testing.T) {
   378  	if testing.Short() {
   379  		t.SkipNow()
   380  	}
   381  
   382  	type sendBlocksTest struct {
   383  		commonBlocksToMine types.BlockHeight
   384  		localBlocksToMine  types.BlockHeight
   385  		remoteBlocksToMine types.BlockHeight
   386  		msg                string
   387  	}
   388  	tests := []sendBlocksTest{
   389  		{
   390  			msg: "SendBlocks shouldn't do anything when both CSs are at the genesis block",
   391  		},
   392  		{
   393  			commonBlocksToMine: 10,
   394  			msg:                "SendBlocks shouldn't do anything when both CSs are at the same block",
   395  		},
   396  		{
   397  			commonBlocksToMine: 10,
   398  			localBlocksToMine:  5,
   399  			msg:                "SendBlocks shouldn't do anything when the remote CS is behind the local CS",
   400  		},
   401  		{
   402  			commonBlocksToMine: 10,
   403  			remoteBlocksToMine: 5,
   404  			msg:                "SendBlocks should catch up the local CS to the remote CS when it is behind",
   405  		},
   406  		{
   407  			remoteBlocksToMine: 10,
   408  			localBlocksToMine:  5,
   409  			msg:                "SendBlocks should reorg the local CS when the remote CS's chain is longer",
   410  		},
   411  		{
   412  			commonBlocksToMine: 10,
   413  			remoteBlocksToMine: 10,
   414  			localBlocksToMine:  5,
   415  			msg:                "SendBlocks should reorg the local CS when the remote CS's chain is longer",
   416  		},
   417  		{
   418  			remoteBlocksToMine: MaxCatchUpBlocks - 1,
   419  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   420  		},
   421  		{
   422  			remoteBlocksToMine: MaxCatchUpBlocks - 1,
   423  			localBlocksToMine:  MaxCatchUpBlocks - 2,
   424  			msg:                "SendBlocks should reorg the local CS when the remote CS's chain is longer",
   425  		},
   426  		{
   427  			remoteBlocksToMine: MaxCatchUpBlocks,
   428  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   429  		},
   430  		{
   431  			remoteBlocksToMine: MaxCatchUpBlocks,
   432  			localBlocksToMine:  MaxCatchUpBlocks - 2,
   433  			msg:                "SendBlocks should reorg the local CS when the remote CS's chain is longer",
   434  		},
   435  		{
   436  			remoteBlocksToMine: MaxCatchUpBlocks + 1, // There was a bug that caused SendBlocks to be one block behind when its peer was ahead by (k * MaxCatchUpBlocks) + 1 blocks.
   437  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   438  		},
   439  		{
   440  			remoteBlocksToMine: MaxCatchUpBlocks + 1, // There was a bug that caused SendBlocks to be one block behind when its peer was ahead by (k * MaxCatchUpBlocks) + 1 blocks.
   441  			localBlocksToMine:  MaxCatchUpBlocks - 2,
   442  			msg:                "SendBlocks should reorg the local CS when the remote CS's chain is longer",
   443  		},
   444  		{
   445  			remoteBlocksToMine: 2*MaxCatchUpBlocks + 1,
   446  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   447  		},
   448  		{
   449  			remoteBlocksToMine: 2*MaxCatchUpBlocks + 1,
   450  			localBlocksToMine:  2*MaxCatchUpBlocks - 2,
   451  			msg:                "SendBlocks should reorg the local CS when the remote CS's chain is longer",
   452  		},
   453  		{
   454  			remoteBlocksToMine: 12,
   455  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   456  		},
   457  		{
   458  			remoteBlocksToMine: 15,
   459  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   460  		},
   461  		{
   462  			remoteBlocksToMine: 16,
   463  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   464  		},
   465  		{
   466  			remoteBlocksToMine: 17,
   467  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   468  		},
   469  		{
   470  			remoteBlocksToMine: 23,
   471  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   472  		},
   473  		{
   474  			remoteBlocksToMine: 31,
   475  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   476  		},
   477  		{
   478  			remoteBlocksToMine: 32,
   479  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   480  		},
   481  		{
   482  			remoteBlocksToMine: 33,
   483  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   484  		},
   485  	}
   486  	for i := 1; i < 10; i++ {
   487  		tests = append(tests, sendBlocksTest{
   488  			remoteBlocksToMine: types.BlockHeight(i),
   489  			msg:                "SendBlocks should catch up when the remote CS is ahead",
   490  		})
   491  	}
   492  
   493  	for i, tt := range tests {
   494  		// Create the "remote" peer.
   495  		remoteCST, err := blankConsensusSetTester(filepath.Join("TestRPCSendBlocks - remote", strconv.Itoa(i)))
   496  		if err != nil {
   497  			t.Fatal(err)
   498  		}
   499  		// Create the "local" peer.
   500  		localCST, err := blankConsensusSetTester(filepath.Join("TestRPCSendBlocks - local", strconv.Itoa(i)))
   501  		if err != nil {
   502  			t.Fatal(err)
   503  		}
   504  
   505  		localCST.cs.gateway.Connect(remoteCST.cs.gateway.Address())
   506  		// Wait a second to let the OnConnectRPCs finish
   507  		time.Sleep(100 * time.Millisecond)
   508  
   509  		// Mine blocks.
   510  		for i := types.BlockHeight(0); i < tt.commonBlocksToMine; i++ {
   511  			b, err := remoteCST.miner.FindBlock()
   512  			if err != nil {
   513  				t.Fatal(err)
   514  			}
   515  			err = remoteCST.cs.managedAcceptBlock(b)
   516  			if err != nil {
   517  				t.Fatal(err)
   518  			}
   519  			err = localCST.cs.managedAcceptBlock(b)
   520  			if err != nil {
   521  				t.Fatal(err)
   522  			}
   523  		}
   524  		for i := types.BlockHeight(0); i < tt.remoteBlocksToMine; i++ {
   525  			b, err := remoteCST.miner.FindBlock()
   526  			if err != nil {
   527  				t.Fatal(err)
   528  			}
   529  			err = remoteCST.cs.managedAcceptBlock(b)
   530  			if err != nil {
   531  				t.Fatal(err)
   532  			}
   533  		}
   534  		for i := types.BlockHeight(0); i < tt.localBlocksToMine; i++ {
   535  			b, err := localCST.miner.FindBlock()
   536  			if err != nil {
   537  				t.Fatal(err)
   538  			}
   539  			err = localCST.cs.managedAcceptBlock(b)
   540  			if err != nil {
   541  				t.Fatal(err)
   542  			}
   543  		}
   544  
   545  		localCurrentBlockID := localCST.cs.CurrentBlock().ID()
   546  		remoteCurrentBlockID := remoteCST.cs.CurrentBlock().ID()
   547  
   548  		err = localCST.cs.gateway.RPC(remoteCST.cs.gateway.Address(), "SendBlocks", localCST.cs.threadedReceiveBlocks)
   549  		if err != nil {
   550  			t.Error(err)
   551  		}
   552  
   553  		// Assume that if remoteBlocksToMine is greater than localBlocksToMine, then
   554  		// the local CS must have received the new blocks (and reorged).
   555  		if tt.remoteBlocksToMine > tt.localBlocksToMine {
   556  			// Verify that the remote cs did not change.
   557  			if remoteCST.cs.CurrentBlock().ID() != remoteCurrentBlockID {
   558  				t.Errorf("%v: the remote CS is at a different current block than before SendBlocks", tt.msg)
   559  			}
   560  			// Verify that the local cs got the new blocks.
   561  			if localCST.cs.Height() != remoteCST.cs.Height() {
   562  				t.Errorf("%v: expected height %v, got %v", tt.msg, remoteCST.cs.Height(), localCST.cs.Height())
   563  			}
   564  			if localCST.cs.CurrentBlock().ID() != remoteCST.cs.CurrentBlock().ID() {
   565  				t.Errorf("%v: remote and local CSTs have different current blocks", tt.msg)
   566  			}
   567  		} else {
   568  			// Verify that the local cs did not change.
   569  			if localCST.cs.CurrentBlock().ID() != localCurrentBlockID {
   570  				t.Errorf("%v: the local CS is at a different current block than before SendBlocks", tt.msg)
   571  			}
   572  		}
   573  
   574  		// Cleanup.
   575  		localCST.cs.gateway.Disconnect(remoteCST.cs.gateway.Address())
   576  		remoteCST.cs.gateway.Disconnect(localCST.cs.gateway.Address())
   577  		err = localCST.Close()
   578  		if err != nil {
   579  			t.Fatal(err)
   580  		}
   581  		err = remoteCST.Close()
   582  		if err != nil {
   583  			t.Fatal(err)
   584  		}
   585  	}
   586  }
   587  
   588  // TestRPCSendBlockSendsOnlyNecessaryBlocks tests that the SendBlocks RPC only
   589  // sends blocks that the caller does not have and that are part of the longest
   590  // chain.
   591  func TestRPCSendBlockSendsOnlyNecessaryBlocks(t *testing.T) {
   592  	if testing.Short() {
   593  		t.SkipNow()
   594  	}
   595  
   596  	// Create the "remote" peer.
   597  	cst, err := blankConsensusSetTester("TestRPCSendBlockSendsOnlyNecessaryBlocks - remote")
   598  	if err != nil {
   599  		t.Fatal(err)
   600  	}
   601  	defer cst.Close()
   602  	// Create the "local" peer.
   603  	//
   604  	// We create this peer manually (not using blankConsensusSetTester) so that we
   605  	// can connect it to the remote peer before calling consensus.New so as to
   606  	// prevent SendBlocks from triggering on Connect.
   607  	testdir := build.TempDir(modules.ConsensusDir, "TestRPCSendBlockSendsOnlyNecessaryBlocks - local")
   608  	g, err := gateway.New("localhost:0", filepath.Join(testdir, modules.GatewayDir))
   609  	if err != nil {
   610  		t.Fatal(err)
   611  	}
   612  	defer g.Close()
   613  	err = g.Connect(cst.cs.gateway.Address())
   614  	if err != nil {
   615  		t.Fatal(err)
   616  	}
   617  	cs, err := New(g, filepath.Join(testdir, modules.ConsensusDir))
   618  	if err != nil {
   619  		t.Fatal(err)
   620  	}
   621  	defer cs.Close()
   622  
   623  	// Add a few initial blocks to both consensus sets. These are the blocks we
   624  	// want to make sure SendBlocks is not sending unnecessarily as both parties
   625  	// already have them.
   626  	knownBlocks := make(map[types.BlockID]struct{})
   627  	for i := 0; i < 20; i++ {
   628  		b, err := cst.miner.FindBlock()
   629  		if err != nil {
   630  			t.Fatal(err)
   631  		}
   632  		err = cst.cs.managedAcceptBlock(b)
   633  		if err != nil {
   634  			t.Fatal(err)
   635  		}
   636  		err = cs.managedAcceptBlock(b)
   637  		if err != nil {
   638  			t.Fatal(err)
   639  		}
   640  		knownBlocks[b.ID()] = struct{}{}
   641  	}
   642  
   643  	// Add a few blocks to only the remote peer and store which blocks we add.
   644  	addedBlocks := make(map[types.BlockID]struct{})
   645  	for i := 0; i < 20; i++ {
   646  		b, err := cst.miner.FindBlock()
   647  		if err != nil {
   648  			t.Fatal(err)
   649  		}
   650  		err = cst.cs.managedAcceptBlock(b)
   651  		if err != nil {
   652  			t.Fatal(err)
   653  		}
   654  		addedBlocks[b.ID()] = struct{}{}
   655  	}
   656  
   657  	err = cs.gateway.RPC(cst.cs.gateway.Address(), "SendBlocks", func(conn modules.PeerConn) error {
   658  		// Get blockIDs to send.
   659  		var history [32]types.BlockID
   660  		cs.mu.RLock()
   661  		err := cs.db.View(func(tx *bolt.Tx) error {
   662  			history = blockHistory(tx)
   663  			return nil
   664  		})
   665  		cs.mu.RUnlock()
   666  		if err != nil {
   667  			return err
   668  		}
   669  
   670  		// Send the block ids.
   671  		if err := encoding.WriteObject(conn, history); err != nil {
   672  			return err
   673  		}
   674  
   675  		moreAvailable := true
   676  		for moreAvailable {
   677  			// Read a slice of blocks from the wire.
   678  			var newBlocks []types.Block
   679  			if err := encoding.ReadObject(conn, &newBlocks, uint64(MaxCatchUpBlocks)*types.BlockSizeLimit); err != nil {
   680  				return err
   681  			}
   682  			if err := encoding.ReadObject(conn, &moreAvailable, 1); err != nil {
   683  				return err
   684  			}
   685  
   686  			// Check if the block needed to be sent.
   687  			for _, newB := range newBlocks {
   688  				_, ok := knownBlocks[newB.ID()]
   689  				if ok {
   690  					t.Error("SendBlocks sent an unnecessary block that the caller already had")
   691  					continue
   692  				}
   693  				_, ok = addedBlocks[newB.ID()]
   694  				if !ok {
   695  					t.Error("SendBlocks sent an unnecessary block that the caller did not have")
   696  				}
   697  			}
   698  		}
   699  		return nil
   700  	})
   701  	if err != nil {
   702  		t.Fatal(err)
   703  	}
   704  }
   705  
   706  // mock PeerConns for testing peer conns that fail reading or writing.
   707  type (
   708  	mockPeerConnFailingReader struct {
   709  		modules.PeerConn
   710  	}
   711  	mockPeerConnFailingWriter struct {
   712  		modules.PeerConn
   713  	}
   714  )
   715  
   716  var (
   717  	errFailingReader = errors.New("failing reader")
   718  	errFailingWriter = errors.New("failing writer")
   719  )
   720  
   721  // Read is a mock implementation of modules.PeerConn.Read that always returns
   722  // an error.
   723  func (mockPeerConnFailingReader) Read([]byte) (int, error) {
   724  	return 0, errFailingReader
   725  }
   726  
   727  // Write is a mock implementation of modules.PeerConn.Write that always returns
   728  // an error.
   729  func (mockPeerConnFailingWriter) Write([]byte) (int, error) {
   730  	return 0, errFailingWriter
   731  }
   732  
   733  // TestSendBlk probes the ConsensusSet.rpcSendBlk method and tests that it
   734  // correctly receives block ids and writes out the corresponding blocks.
   735  func TestSendBlk(t *testing.T) {
   736  	cst, err := blankConsensusSetTester("TestSendBlk")
   737  	if err != nil {
   738  		t.Fatal(err)
   739  	}
   740  	defer cst.Close()
   741  
   742  	p1, p2 := net.Pipe()
   743  	fnErr := make(chan error)
   744  
   745  	tests := []struct {
   746  		id      types.BlockID
   747  		conn    modules.PeerConn
   748  		fn      func() // handle reading and writing over the pipe to the mock conn.
   749  		errWant error
   750  		msg     string
   751  	}{
   752  		// TODO: Test with a failing database.
   753  		// Test with a failing reader.
   754  		{
   755  			conn:    mockPeerConnFailingReader{PeerConn: p1},
   756  			fn:      func() { fnErr <- nil },
   757  			errWant: errFailingReader,
   758  			msg:     "expected rpcSendBlk to error with a failing reader conn",
   759  		},
   760  		// Test with a block id not found in the blockmap.
   761  		{
   762  			conn: p1,
   763  			fn: func() {
   764  				// Write a block id to the conn.
   765  				fnErr <- encoding.WriteObject(p2, types.BlockID{})
   766  			},
   767  			errWant: errNilItem,
   768  			msg:     "expected rpcSendBlk to error with a nonexistent block id",
   769  		},
   770  		// Test with a failing writer.
   771  		{
   772  			conn: mockPeerConnFailingWriter{PeerConn: p1},
   773  			fn: func() {
   774  				// Write a valid block id to the conn.
   775  				fnErr <- encoding.WriteObject(p2, types.GenesisID)
   776  			},
   777  			errWant: errFailingWriter,
   778  			msg:     "expected rpcSendBlk to error with a failing writer conn",
   779  		},
   780  		// Test with a valid conn and valid block.
   781  		{
   782  			conn: p1,
   783  			fn: func() {
   784  				// Write a valid block id to the conn.
   785  				if err := encoding.WriteObject(p2, types.GenesisID); err != nil {
   786  					fnErr <- err
   787  				}
   788  
   789  				// Read the block written to the conn.
   790  				var block types.Block
   791  				if err := encoding.ReadObject(p2, &block, types.BlockSizeLimit); err != nil {
   792  					fnErr <- err
   793  				}
   794  				// Verify the block is the expected block.
   795  				if block.ID() != types.GenesisID {
   796  					fnErr <- fmt.Errorf("rpcSendBlk wrote a different block to conn than the block requested. requested block id: %v, received block id: %v", types.GenesisID, block.ID())
   797  				}
   798  
   799  				fnErr <- nil
   800  			},
   801  			errWant: nil,
   802  			msg:     "expected rpcSendBlk to succeed with a valid conn and valid block",
   803  		},
   804  	}
   805  	for _, tt := range tests {
   806  		go tt.fn()
   807  		err := cst.cs.rpcSendBlk(tt.conn)
   808  		if err != tt.errWant {
   809  			t.Errorf("%s: expected to fail with `%v', got: `%v'", tt.msg, tt.errWant, err)
   810  		}
   811  		err = <-fnErr
   812  		if err != nil {
   813  			t.Fatal(err)
   814  		}
   815  	}
   816  }
   817  
   818  // TestThreadedReceiveBlock probes the RPCFunc returned by
   819  // cs.threadedReceiveBlock and tests that it correctly requests a block id and
   820  // receives a block. Also tests that the block is correctly (not) accepted into
   821  // the consensus set.
   822  func TestThreadedReceiveBlock(t *testing.T) {
   823  	cst, err := blankConsensusSetTester("TestThreadedReceiveBlock")
   824  	if err != nil {
   825  		t.Fatal(err)
   826  	}
   827  	defer cst.Close()
   828  
   829  	p1, p2 := net.Pipe()
   830  	fnErr := make(chan error)
   831  
   832  	tests := []struct {
   833  		id      types.BlockID
   834  		conn    modules.PeerConn
   835  		fn      func() // handle reading and writing over the pipe to the mock conn.
   836  		errWant error
   837  		msg     string
   838  	}{
   839  		// Test with failing writer.
   840  		{
   841  			conn:    mockPeerConnFailingWriter{PeerConn: p1},
   842  			fn:      func() { fnErr <- nil },
   843  			errWant: errFailingWriter,
   844  			msg:     "the function returned from threadedReceiveBlock should fail with a PeerConn with a failing writer",
   845  		},
   846  		// Test with failing reader.
   847  		{
   848  			conn: mockPeerConnFailingReader{PeerConn: p1},
   849  			fn: func() {
   850  				// Read the id written to conn.
   851  				var id types.BlockID
   852  				if err := encoding.ReadObject(p2, &id, crypto.HashSize); err != nil {
   853  					fnErr <- err
   854  				}
   855  				// Verify the id is the expected id.
   856  				expectedID := types.BlockID{}
   857  				if id != expectedID {
   858  					fnErr <- fmt.Errorf("id written to conn was %v, but id received was %v", expectedID, id)
   859  				}
   860  				fnErr <- nil
   861  			},
   862  			errWant: errFailingReader,
   863  			msg:     "the function returned from threadedReceiveBlock should fail with a PeerConn with a failing reader",
   864  		},
   865  		// Test with a valid conn, but an invalid block.
   866  		{
   867  			id:   types.BlockID{1},
   868  			conn: p1,
   869  			fn: func() {
   870  				// Read the id written to conn.
   871  				var id types.BlockID
   872  				if err := encoding.ReadObject(p2, &id, crypto.HashSize); err != nil {
   873  					fnErr <- err
   874  				}
   875  				// Verify the id is the expected id.
   876  				expectedID := types.BlockID{1}
   877  				if id != expectedID {
   878  					fnErr <- fmt.Errorf("id written to conn was %v, but id received was %v", expectedID, id)
   879  				}
   880  
   881  				// Write an invalid block to conn.
   882  				block := types.Block{}
   883  				if err := encoding.WriteObject(p2, block); err != nil {
   884  					fnErr <- err
   885  				}
   886  
   887  				fnErr <- nil
   888  			},
   889  			errWant: errOrphan,
   890  			msg:     "the function returned from threadedReceiveBlock should not accept an invalid block",
   891  		},
   892  		// Test with a valid conn and a valid block.
   893  		{
   894  			id:   types.BlockID{2},
   895  			conn: p1,
   896  			fn: func() {
   897  				// Read the id written to conn.
   898  				var id types.BlockID
   899  				if err := encoding.ReadObject(p2, &id, crypto.HashSize); err != nil {
   900  					fnErr <- err
   901  				}
   902  				// Verify the id is the expected id.
   903  				expectedID := types.BlockID{2}
   904  				if id != expectedID {
   905  					fnErr <- fmt.Errorf("id written to conn was %v, but id received was %v", expectedID, id)
   906  				}
   907  
   908  				// Write a valid block to conn.
   909  				block, err := cst.miner.FindBlock()
   910  				if err != nil {
   911  					fnErr <- err
   912  				}
   913  				if err := encoding.WriteObject(p2, block); err != nil {
   914  					fnErr <- err
   915  				}
   916  
   917  				fnErr <- nil
   918  			},
   919  			errWant: nil,
   920  			msg:     "the function returned from manageddReceiveBlock should accept a valid block",
   921  		},
   922  	}
   923  	for _, tt := range tests {
   924  		managedReceiveFN := cst.cs.threadedReceiveBlock(tt.id)
   925  		go tt.fn()
   926  		err := managedReceiveFN(tt.conn)
   927  		if err != tt.errWant {
   928  			t.Errorf("%s: expected to fail with `%v', got: `%v'", tt.msg, tt.errWant, err)
   929  		}
   930  		err = <-fnErr
   931  		if err != nil {
   932  			t.Fatal(err)
   933  		}
   934  	}
   935  }
   936  
   937  // TestIntegrationSendBlkRPC probes the SendBlk RPC and tests that blocks are
   938  // correctly requested, received, and accepted into the consensus set.
   939  func TestIntegrationSendBlkRPC(t *testing.T) {
   940  	if testing.Short() {
   941  		t.SkipNow()
   942  	}
   943  	cst1, err := blankConsensusSetTester("TestIntegrationSendBlkRPC1")
   944  	if err != nil {
   945  		t.Fatal(err)
   946  	}
   947  	defer cst1.Close()
   948  	cst2, err := blankConsensusSetTester("TestIntegrationSendBlkRPC2")
   949  	if err != nil {
   950  		t.Fatal(err)
   951  	}
   952  	defer cst2.Close()
   953  
   954  	err = cst1.cs.gateway.Connect(cst2.cs.gateway.Address())
   955  	if err != nil {
   956  		t.Fatal(err)
   957  	}
   958  	err = cst2.cs.gateway.Connect(cst1.cs.gateway.Address())
   959  	if err != nil {
   960  		t.Fatal(err)
   961  	}
   962  	// Sleep to give the consensus sets time to finish the background startup
   963  	// routines - if the block mined below is mined before the sets finish
   964  	// synchronizing to eachother, it screws up the test.
   965  	time.Sleep(500 * time.Millisecond)
   966  
   967  	// Test that cst1 doesn't accept a block it's already seen (the genesis block).
   968  	err = cst1.cs.gateway.RPC(cst2.cs.gateway.Address(), "SendBlk", cst1.cs.threadedReceiveBlock(types.GenesisID))
   969  	if err != modules.ErrBlockKnown {
   970  		t.Errorf("cst1 should reject known blocks: expected error '%v', got '%v'", modules.ErrBlockKnown, err)
   971  	}
   972  	// Test that cst2 errors when it doesn't recognize the requested block.
   973  	err = cst1.cs.gateway.RPC(cst2.cs.gateway.Address(), "SendBlk", cst1.cs.threadedReceiveBlock(types.BlockID{}))
   974  	if err != io.EOF {
   975  		t.Errorf("cst2 shouldn't return a block it doesn't recognize: expected error '%v', got '%v'", io.EOF, err)
   976  	}
   977  
   978  	// Test that cst1 accepts a block that extends its longest chain.
   979  	block, err := cst2.miner.FindBlock()
   980  	if err != nil {
   981  		t.Fatal(err)
   982  	}
   983  	err = cst2.cs.managedAcceptBlock(block) // Call managedAcceptBlock so that the block isn't broadcast.
   984  	if err != nil {
   985  		t.Fatal(err)
   986  	}
   987  	err = cst1.cs.gateway.RPC(cst2.cs.gateway.Address(), "SendBlk", cst1.cs.threadedReceiveBlock(block.ID()))
   988  	if err != nil {
   989  		t.Errorf("cst1 should accept a block that extends its longest chain: expected nil error, got '%v'", err)
   990  	}
   991  
   992  	// Test that cst2 accepts a block that extends its longest chain.
   993  	block, err = cst1.miner.FindBlock()
   994  	if err != nil {
   995  		t.Fatal(err)
   996  	}
   997  	err = cst1.cs.managedAcceptBlock(block) // Call managedAcceptBlock so that the block isn't broadcast.
   998  	if err != nil {
   999  		t.Fatal(err)
  1000  	}
  1001  	err = cst2.cs.gateway.RPC(cst1.cs.gateway.Address(), "SendBlk", cst2.cs.threadedReceiveBlock(block.ID()))
  1002  	if err != nil {
  1003  		t.Errorf("cst2 should accept a block that extends its longest chain: expected nil error, got '%v'", err)
  1004  	}
  1005  
  1006  	// Test that cst1 doesn't accept an orphan block.
  1007  	block, err = cst2.miner.FindBlock()
  1008  	if err != nil {
  1009  		t.Fatal(err)
  1010  	}
  1011  	err = cst2.cs.managedAcceptBlock(block) // Call managedAcceptBlock so that the block isn't broadcast.
  1012  	if err != nil {
  1013  		t.Fatal(err)
  1014  	}
  1015  	block, err = cst2.miner.FindBlock()
  1016  	if err != nil {
  1017  		t.Fatal(err)
  1018  	}
  1019  	err = cst2.cs.managedAcceptBlock(block) // Call managedAcceptBlock so that the block isn't broadcast.
  1020  	if err != nil {
  1021  		t.Fatal(err)
  1022  	}
  1023  	err = cst1.cs.gateway.RPC(cst2.cs.gateway.Address(), "SendBlk", cst1.cs.threadedReceiveBlock(block.ID()))
  1024  	if err != errOrphan {
  1025  		t.Errorf("cst1 should not accept an orphan block: expected error '%v', got '%v'", errOrphan, err)
  1026  	}
  1027  }
  1028  
  1029  type mockGatewayCallsRPC struct {
  1030  	modules.Gateway
  1031  	rpcCalled chan string
  1032  }
  1033  
  1034  func (g *mockGatewayCallsRPC) RPC(addr modules.NetAddress, name string, fn modules.RPCFunc) error {
  1035  	g.rpcCalled <- name
  1036  	return nil
  1037  }
  1038  
  1039  // TestRelayHeader tests that rpcRelayHeader requests the corresponding blocks
  1040  // to valid headers with known parents, or requests the block history to orphan
  1041  // headers.
  1042  func TestRelayHeader(t *testing.T) {
  1043  	cst, err := blankConsensusSetTester("TestRelayHeader")
  1044  	if err != nil {
  1045  		t.Fatal(err)
  1046  	}
  1047  	defer cst.Close()
  1048  
  1049  	mg := &mockGatewayCallsRPC{
  1050  		rpcCalled: make(chan string),
  1051  	}
  1052  	cst.cs.gateway = mg
  1053  
  1054  	p1, p2 := net.Pipe()
  1055  
  1056  	// Valid block that rpcRelayHeader should accept.
  1057  	validBlock, err := cst.miner.FindBlock()
  1058  	if err != nil {
  1059  		t.Fatal(err)
  1060  	}
  1061  
  1062  	// A block in the near future that rpcRelayHeader return an error for, but
  1063  	// still request the corresponding block.
  1064  	block, target, err := cst.miner.BlockForWork()
  1065  	if err != nil {
  1066  		t.Fatal(err)
  1067  	}
  1068  	block.Timestamp = types.CurrentTimestamp() + 2 + types.FutureThreshold
  1069  	futureBlock, _ := cst.miner.SolveBlock(block, target)
  1070  
  1071  	tests := []struct {
  1072  		header  types.BlockHeader
  1073  		errWant error
  1074  		errMSG  string
  1075  		rpcWant string
  1076  		rpcMSG  string
  1077  	}{
  1078  		// Test that rpcRelayHeader rejects known blocks.
  1079  		{
  1080  			header:  types.GenesisBlock.Header(),
  1081  			errWant: modules.ErrBlockKnown,
  1082  			errMSG:  "rpcRelayHeader should reject headers to known blocks",
  1083  		},
  1084  		// Test that rpcRelayHeader requests the parent blocks of orphan headers.
  1085  		{
  1086  			header:  types.BlockHeader{},
  1087  			errWant: nil,
  1088  			errMSG:  "rpcRelayHeader should not return an error for orphan headers",
  1089  			rpcWant: "SendBlocks",
  1090  			rpcMSG:  "rpcRelayHeader should request blocks when the relayed header is an orphan",
  1091  		},
  1092  		// Test that rpcRelayHeader accepts a valid header that extends the longest chain.
  1093  		{
  1094  			header:  validBlock.Header(),
  1095  			errWant: nil,
  1096  			errMSG:  "rpcRelayHeader should accept a valid header",
  1097  			rpcWant: "SendBlk",
  1098  			rpcMSG:  "rpcRelayHeader should request the block of a valid header",
  1099  		},
  1100  		// Test that rpcRelayHeader requests a future, but otherwise valid block.
  1101  		{
  1102  			header:  futureBlock.Header(),
  1103  			errWant: nil,
  1104  			errMSG:  "rpcRelayHeader should not return an error for a future header",
  1105  			rpcWant: "SendBlk",
  1106  			rpcMSG:  "rpcRelayHeader should request the corresponding block to a future, but otherwise valid header",
  1107  		},
  1108  	}
  1109  	errChan := make(chan error)
  1110  	for _, tt := range tests {
  1111  		go func() {
  1112  			errChan <- encoding.WriteObject(p1, tt.header)
  1113  		}()
  1114  		err = cst.cs.rpcRelayHeader(p2)
  1115  		if err != tt.errWant {
  1116  			t.Errorf("%s: expected '%v', got '%v'", tt.errMSG, tt.errWant, err)
  1117  		}
  1118  		err = <-errChan
  1119  		if err != nil {
  1120  			t.Fatal(err)
  1121  		}
  1122  		if tt.rpcWant == "" {
  1123  			select {
  1124  			case rpc := <-mg.rpcCalled:
  1125  				t.Errorf("no RPC call expected, but '%v' was called", rpc)
  1126  			case <-time.After(10 * time.Millisecond):
  1127  			}
  1128  		} else {
  1129  			select {
  1130  			case rpc := <-mg.rpcCalled:
  1131  				if rpc != tt.rpcWant {
  1132  					t.Errorf("%s: expected '%v', got '%v'", tt.rpcMSG, tt.rpcWant, rpc)
  1133  				}
  1134  			case <-time.After(10 * time.Millisecond):
  1135  				t.Errorf("%s: expected '%v', but no RPC was called", tt.rpcMSG, tt.rpcWant)
  1136  			}
  1137  		}
  1138  	}
  1139  }
  1140  
  1141  // TestIntegrationBroadcastRelayHeader checks that broadcasting RelayHeader
  1142  // causes peers to also broadcast the header (if the block is valid).
  1143  func TestIntegrationBroadcastRelayHeader(t *testing.T) {
  1144  	if testing.Short() {
  1145  		t.SkipNow()
  1146  	}
  1147  	// Setup consensus sets.
  1148  	cst1, err := blankConsensusSetTester("TestIntegrationBroadcastRelayHeader1")
  1149  	if err != nil {
  1150  		t.Fatal(err)
  1151  	}
  1152  	defer cst1.Close()
  1153  	cst2, err := blankConsensusSetTester("TestIntegrationBroadcastRelayHeader2")
  1154  	if err != nil {
  1155  		t.Fatal(err)
  1156  	}
  1157  	defer cst2.Close()
  1158  	// Setup mock gateway.
  1159  	mg := &mockGatewayDoesBroadcast{
  1160  		Gateway:         cst2.cs.gateway,
  1161  		broadcastCalled: make(chan struct{}),
  1162  	}
  1163  	cst2.cs.gateway = mg
  1164  	err = cst1.cs.gateway.Connect(cst2.cs.gateway.Address())
  1165  	if err != nil {
  1166  		t.Fatal(err)
  1167  	}
  1168  
  1169  	// Test that broadcasting an invalid block header over RelayHeader on cst1.cs
  1170  	// does not result in cst2.cs.gateway receiving a broadcast.
  1171  	cst1.cs.gateway.Broadcast("RelayHeader", types.BlockHeader{}, cst1.cs.gateway.Peers())
  1172  	select {
  1173  	case <-mg.broadcastCalled:
  1174  		t.Fatal("RelayHeader broadcasted an invalid block header")
  1175  	case <-time.After(200 * time.Millisecond):
  1176  	}
  1177  
  1178  	// Test that broadcasting a valid block header over RelayHeader on cst1.cs
  1179  	// causes cst2.cs.gateway to receive a broadcast.
  1180  	validBlock, err := cst1.miner.FindBlock()
  1181  	if err != nil {
  1182  		t.Fatal(err)
  1183  	}
  1184  	err = cst1.cs.managedAcceptBlock(validBlock)
  1185  	if err != nil {
  1186  		t.Fatal(err)
  1187  	}
  1188  	cst1.cs.gateway.Broadcast("RelayHeader", validBlock.Header(), cst1.cs.gateway.Peers())
  1189  	select {
  1190  	case <-mg.broadcastCalled:
  1191  		// Broadcast is called twice, once to broadcast blocks to peers <= v0.5.1
  1192  		// and once to broadcast block headers to peers > v0.5.1.
  1193  		<-mg.broadcastCalled
  1194  	case <-time.After(200 * time.Millisecond):
  1195  		t.Fatal("RelayHeader didn't broadcast a valid block header")
  1196  	}
  1197  }
  1198  
  1199  // TestIntegrationRelaySynchronize tests that blocks are relayed as they are
  1200  // accepted and that peers stay synchronized. This test is header/block
  1201  // broadcast agnostic.  When build.Version <= 0.5.1 block relaying will be
  1202  // tested. When build.Version > 0.5.1 header relaying will be tested.
  1203  func TestIntegrationRelaySynchronize(t *testing.T) {
  1204  	if testing.Short() {
  1205  		t.SkipNow()
  1206  	}
  1207  
  1208  	cst1, err := blankConsensusSetTester("TestRelaySynchronize1")
  1209  	if err != nil {
  1210  		t.Fatal(err)
  1211  	}
  1212  	defer cst1.Close()
  1213  	cst2, err := blankConsensusSetTester("TestRelaySynchronize2")
  1214  	if err != nil {
  1215  		t.Fatal(err)
  1216  	}
  1217  	defer cst2.Close()
  1218  	cst3, err := blankConsensusSetTester("TestRelaySynchronize3")
  1219  	if err != nil {
  1220  		t.Fatal(err)
  1221  	}
  1222  	defer cst3.Close()
  1223  
  1224  	// Connect them like so: cst1 <-> cst2 <-> cst3
  1225  	err = cst1.gateway.Connect(cst2.gateway.Address())
  1226  	if err != nil {
  1227  		t.Fatal(err)
  1228  	}
  1229  	err = cst2.gateway.Connect(cst3.gateway.Address())
  1230  	if err != nil {
  1231  		t.Fatal(err)
  1232  	}
  1233  	// Make sure cst1 is not connected to cst3.
  1234  	cst1.gateway.Disconnect(cst3.gateway.Address())
  1235  	cst3.gateway.Disconnect(cst1.gateway.Address())
  1236  
  1237  	// Spin until the connection calls have completed.
  1238  	for i := 0; i < 100; i++ {
  1239  		time.Sleep(50 * time.Millisecond)
  1240  		if len(cst1.gateway.Peers()) >= 1 && len(cst3.gateway.Peers()) >= 1 {
  1241  			break
  1242  		}
  1243  	}
  1244  	if len(cst1.gateway.Peers()) < 1 || len(cst3.gateway.Peers()) < 1 {
  1245  		t.Fatal("Peer connection has failed.")
  1246  	}
  1247  
  1248  	// Mine a block on cst1, expecting the block to propagate from cst1 to
  1249  	// cst2, and then to cst3.
  1250  	b, err := cst1.miner.AddBlock()
  1251  	if err != nil {
  1252  		t.Fatal(err)
  1253  	}
  1254  
  1255  	// Spin until the block has propagated to cst2.
  1256  	for i := 0; i < 100; i++ {
  1257  		time.Sleep(50 * time.Millisecond)
  1258  		if cst2.cs.CurrentBlock().ID() == b.ID() {
  1259  			break
  1260  		}
  1261  	}
  1262  	if cst2.cs.CurrentBlock().ID() != b.ID() {
  1263  		t.Fatal("Block propagation has failed")
  1264  	}
  1265  
  1266  	// Spin until the block has propagated to cst3.
  1267  	for i := 0; i < 100; i++ {
  1268  		time.Sleep(50 * time.Millisecond)
  1269  		if cst3.cs.CurrentBlock().ID() == b.ID() {
  1270  			break
  1271  		}
  1272  	}
  1273  	if cst3.cs.CurrentBlock().ID() != b.ID() {
  1274  		t.Fatal("Block propagation has failed")
  1275  	}
  1276  
  1277  	// Mine a block on cst2.
  1278  	b, err = cst2.miner.AddBlock()
  1279  	if err != nil {
  1280  		t.Fatal(err)
  1281  	}
  1282  	// Spin until the block has propagated.
  1283  	for i := 0; i < 100; i++ {
  1284  		time.Sleep(50 * time.Millisecond)
  1285  		if cst1.cs.CurrentBlock().ID() == b.ID() {
  1286  			break
  1287  		}
  1288  	}
  1289  	if cst1.cs.CurrentBlock().ID() != b.ID() {
  1290  		t.Fatal("block propagation has failed")
  1291  	}
  1292  	for i := 0; i < 100; i++ {
  1293  		time.Sleep(50 * time.Millisecond)
  1294  		if cst3.cs.CurrentBlock().ID() == b.ID() {
  1295  			break
  1296  		}
  1297  	}
  1298  	if cst3.cs.CurrentBlock().ID() != b.ID() {
  1299  		t.Fatal("block propagation has failed")
  1300  	}
  1301  
  1302  	// Mine a block on cst3.
  1303  	b, err = cst3.miner.AddBlock()
  1304  	if err != nil {
  1305  		t.Fatal(err)
  1306  	}
  1307  	// Spin until the block has propagated.
  1308  	for i := 0; i < 100; i++ {
  1309  		time.Sleep(50 * time.Millisecond)
  1310  		if cst1.cs.CurrentBlock().ID() == b.ID() {
  1311  			break
  1312  		}
  1313  	}
  1314  	if cst1.cs.CurrentBlock().ID() != b.ID() {
  1315  		t.Fatal("block propagation has failed")
  1316  	}
  1317  	for i := 0; i < 100; i++ {
  1318  		time.Sleep(50 * time.Millisecond)
  1319  		if cst2.cs.CurrentBlock().ID() == b.ID() {
  1320  			break
  1321  		}
  1322  	}
  1323  	if cst2.cs.CurrentBlock().ID() != b.ID() {
  1324  		t.Fatal("block propagation has failed")
  1325  	}
  1326  
  1327  	// Check that cst1 and cst3 are not peers, if they are peers then this test
  1328  	// is invalid because it has failed to be certain that blocks can make
  1329  	// multiple hops.
  1330  	if len(cst1.gateway.Peers()) != 1 || cst1.gateway.Peers()[0].NetAddress == cst3.gateway.Address() {
  1331  		t.Fatal("Test is invalid, cst1 and cst3 have connected to eachother")
  1332  	}
  1333  	if len(cst3.gateway.Peers()) != 1 || cst3.gateway.Peers()[0].NetAddress == cst1.gateway.Address() {
  1334  		t.Fatal("Test is invalid, cst3 and cst1 have connected to eachother")
  1335  	}
  1336  }
  1337  
  1338  // mockConnMockReadWrite is a mock implementation of net.Conn that returns
  1339  // fails reading or writing if readErr or writeErr is non-nil, respectively.
  1340  type mockConnMockReadWrite struct {
  1341  	net.Conn
  1342  	readErr  error
  1343  	writeErr error
  1344  }
  1345  
  1346  // Read is a mock implementation of conn.Read that fails with the mock error if
  1347  // readErr != nil.
  1348  func (conn mockConnMockReadWrite) Read(b []byte) (n int, err error) {
  1349  	if conn.readErr != nil {
  1350  		return 0, conn.readErr
  1351  	}
  1352  	return conn.Conn.Read(b)
  1353  }
  1354  
  1355  // Write is a mock implementation of conn.Write that fails with the mock error
  1356  // if writeErr != nil.
  1357  func (conn mockConnMockReadWrite) Write(b []byte) (n int, err error) {
  1358  	if conn.writeErr != nil {
  1359  		return 0, conn.writeErr
  1360  	}
  1361  	return conn.Conn.Write(b)
  1362  }
  1363  
  1364  // mockNetError is a mock net.Error.
  1365  type mockNetError struct {
  1366  	error
  1367  	timeout   bool
  1368  	temporary bool
  1369  }
  1370  
  1371  // Timeout is a mock implementation of net.Error.Timeout.
  1372  func (err mockNetError) Timeout() bool {
  1373  	return err.timeout
  1374  }
  1375  
  1376  // Temporary is a mock implementation of net.Error.Temporary.
  1377  func (err mockNetError) Temporary() bool {
  1378  	return err.temporary
  1379  }
  1380  
  1381  // TestThreadedReceiveBlocksStalls tests that threadedReceiveBlocks returns
  1382  // errSendBlocksStalled when the connection times out before a block is
  1383  // received.
  1384  func TestThreadedReceiveBlocksStalls(t *testing.T) {
  1385  	if testing.Short() {
  1386  		t.SkipNow()
  1387  	}
  1388  
  1389  	cst, err := blankConsensusSetTester("TestThreadedReceiveBlocksStalls")
  1390  	if err != nil {
  1391  		t.Fatal(err)
  1392  	}
  1393  	defer cst.Close()
  1394  
  1395  	p1, p2 := net.Pipe()
  1396  	writeTimeoutConn := mockConnMockReadWrite{
  1397  		Conn: p2,
  1398  		writeErr: mockNetError{
  1399  			error:   errors.New("Write timeout"),
  1400  			timeout: true,
  1401  		},
  1402  	}
  1403  	readTimeoutConn := mockConnMockReadWrite{
  1404  		Conn: p2,
  1405  		readErr: mockNetError{
  1406  			error:   errors.New("Read timeout"),
  1407  			timeout: true,
  1408  		},
  1409  	}
  1410  
  1411  	readNetErrConn := mockConnMockReadWrite{
  1412  		Conn: p2,
  1413  		readErr: mockNetError{
  1414  			error: errors.New("mock read net.Error"),
  1415  		},
  1416  	}
  1417  	writeNetErrConn := mockConnMockReadWrite{
  1418  		Conn: p2,
  1419  		writeErr: mockNetError{
  1420  			error: errors.New("mock write net.Error"),
  1421  		},
  1422  	}
  1423  
  1424  	readErrConn := mockConnMockReadWrite{
  1425  		Conn:    p2,
  1426  		readErr: errors.New("mock read err"),
  1427  	}
  1428  	writeErrConn := mockConnMockReadWrite{
  1429  		Conn:     p2,
  1430  		writeErr: errors.New("mock write err"),
  1431  	}
  1432  
  1433  	// Test that threadedReceiveBlocks errors with errSendBlocksStalled when 0
  1434  	// blocks have been sent and the conn times out.
  1435  	err = cst.cs.threadedReceiveBlocks(writeTimeoutConn)
  1436  	if err != errSendBlocksStalled {
  1437  		t.Errorf("expected threadedReceiveBlocks to err with \"%v\", got \"%v\"", errSendBlocksStalled, err)
  1438  	}
  1439  	errChan := make(chan error)
  1440  	go func() {
  1441  		var knownBlocks [32]types.BlockID
  1442  		errChan <- encoding.ReadObject(p1, &knownBlocks, 32*crypto.HashSize)
  1443  	}()
  1444  	err = cst.cs.threadedReceiveBlocks(readTimeoutConn)
  1445  	if err != errSendBlocksStalled {
  1446  		t.Errorf("expected threadedReceiveBlocks to err with \"%v\", got \"%v\"", errSendBlocksStalled, err)
  1447  	}
  1448  	err = <-errChan
  1449  	if err != nil {
  1450  		t.Fatal(err)
  1451  	}
  1452  
  1453  	// Test that threadedReceiveBlocks errors when writing the block history fails.
  1454  	// Test with an error of type net.Error.
  1455  	err = cst.cs.threadedReceiveBlocks(writeNetErrConn)
  1456  	if err != writeNetErrConn.writeErr {
  1457  		t.Errorf("expected threadedReceiveBlocks to err with \"%v\", got \"%v\"", writeNetErrConn.writeErr, err)
  1458  	}
  1459  	// Test with an error of type error.
  1460  	err = cst.cs.threadedReceiveBlocks(writeErrConn)
  1461  	if err != writeErrConn.writeErr {
  1462  		t.Errorf("expected threadedReceiveBlocks to err with \"%v\", got \"%v\"", writeErrConn.writeErr, err)
  1463  	}
  1464  
  1465  	// Test that threadedReceiveBlocks errors when reading blocks fails.
  1466  	// Test with an error of type net.Error.
  1467  	go func() {
  1468  		var knownBlocks [32]types.BlockID
  1469  		errChan <- encoding.ReadObject(p1, &knownBlocks, 32*crypto.HashSize)
  1470  	}()
  1471  	err = cst.cs.threadedReceiveBlocks(readNetErrConn)
  1472  	if err != readNetErrConn.readErr {
  1473  		t.Errorf("expected threadedReceiveBlocks to err with \"%v\", got \"%v\"", readNetErrConn.readErr, err)
  1474  	}
  1475  	err = <-errChan
  1476  	if err != nil {
  1477  		t.Fatal(err)
  1478  	}
  1479  	// Test with an error of type error.
  1480  	go func() {
  1481  		var knownBlocks [32]types.BlockID
  1482  		errChan <- encoding.ReadObject(p1, &knownBlocks, 32*crypto.HashSize)
  1483  	}()
  1484  	err = cst.cs.threadedReceiveBlocks(readErrConn)
  1485  	if err != readErrConn.readErr {
  1486  		t.Errorf("expected threadedReceiveBlocks to err with \"%v\", got \"%v\"", readErrConn.readErr, err)
  1487  	}
  1488  	err = <-errChan
  1489  	if err != nil {
  1490  		t.Fatal(err)
  1491  	}
  1492  
  1493  	// TODO: Test that threadedReceiveBlocks doesn't error with a timeout if it has received one block before this timed out read/write.
  1494  
  1495  	// TODO: Test that threadedReceiveBlocks doesn't error with errSendBlocksStalled if it successfully received one block.
  1496  }
  1497  
  1498  // TestIntegrationSendBlocksStalls tests that the SendBlocks RPC fails with
  1499  // errSendBlockStalled when the RPC timesout and the requesting end has
  1500  // received 0 blocks.
  1501  func TestIntegrationSendBlocksStalls(t *testing.T) {
  1502  	if testing.Short() {
  1503  		t.SkipNow()
  1504  	}
  1505  
  1506  	cstLocal, err := blankConsensusSetTester("TestThreadedReceiveBlocksTimesout - local")
  1507  	if err != nil {
  1508  		t.Fatal(err)
  1509  	}
  1510  	defer cstLocal.Close()
  1511  	cstRemote, err := blankConsensusSetTester("TestThreadedReceiveBlocksTimesout - remote")
  1512  	if err != nil {
  1513  		t.Fatal(err)
  1514  	}
  1515  	defer cstRemote.Close()
  1516  
  1517  	cstLocal.cs.gateway.Connect(cstRemote.cs.gateway.Address())
  1518  
  1519  	// Lock the remote CST so that SendBlocks blocks and timesout.
  1520  	cstRemote.cs.mu.Lock()
  1521  	defer cstRemote.cs.mu.Unlock()
  1522  	err = cstLocal.cs.gateway.RPC(cstRemote.cs.gateway.Address(), "SendBlocks", cstLocal.cs.threadedReceiveBlocks)
  1523  	if err != errSendBlocksStalled {
  1524  		t.Fatal(err)
  1525  	}
  1526  }