github.com/bloxroute-labs/bor@v0.1.4/les/ulc_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package les
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"fmt"
    22  	"math/big"
    23  	"net"
    24  	"reflect"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/maticnetwork/bor/common/mclock"
    29  	"github.com/maticnetwork/bor/core/rawdb"
    30  	"github.com/maticnetwork/bor/crypto"
    31  	"github.com/maticnetwork/bor/light"
    32  	"github.com/maticnetwork/bor/p2p"
    33  	"github.com/maticnetwork/bor/p2p/enode"
    34  )
    35  
    36  func TestULCSyncWithOnePeer(t *testing.T) {
    37  	f := newFullPeerPair(t, 1, 4)
    38  	l := newLightPeer(t, []string{f.Node.String()}, 100)
    39  
    40  	if reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
    41  		t.Fatal("blocks are equal")
    42  	}
    43  	_, _, err := connectPeers(f, l, 2)
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	l.PM.fetcher.lock.Lock()
    48  	l.PM.fetcher.nextRequest()
    49  	l.PM.fetcher.lock.Unlock()
    50  
    51  	if !reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
    52  		t.Fatal("sync doesn't work")
    53  	}
    54  }
    55  
    56  func TestULCReceiveAnnounce(t *testing.T) {
    57  	f := newFullPeerPair(t, 1, 4)
    58  	l := newLightPeer(t, []string{f.Node.String()}, 100)
    59  	fPeer, lPeer, err := connectPeers(f, l, 2)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	l.PM.synchronise(fPeer)
    64  
    65  	//check that the sync is finished correctly
    66  	if !reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
    67  		t.Fatal("sync doesn't work")
    68  	}
    69  	l.PM.peers.lock.Lock()
    70  	if len(l.PM.peers.peers) == 0 {
    71  		t.Fatal("peer list should not be empty")
    72  	}
    73  	l.PM.peers.lock.Unlock()
    74  
    75  	time.Sleep(time.Second)
    76  	//send a signed announce message(payload doesn't matter)
    77  	td := f.PM.blockchain.GetTd(l.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Number.Uint64())
    78  	announce := announceData{
    79  		Number: l.PM.blockchain.CurrentHeader().Number.Uint64() + 1,
    80  		Td:     td.Add(td, big.NewInt(1)),
    81  	}
    82  	announce.sign(f.Key)
    83  	lPeer.SendAnnounce(announce)
    84  }
    85  
    86  func TestULCShouldNotSyncWithTwoPeersOneHaveEmptyChain(t *testing.T) {
    87  	f1 := newFullPeerPair(t, 1, 4)
    88  	f2 := newFullPeerPair(t, 2, 0)
    89  	l := newLightPeer(t, []string{f1.Node.String(), f2.Node.String()}, 100)
    90  	_, _, err := connectPeers(f1, l, 2)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	_, _, err = connectPeers(f2, l, 2)
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	l.PM.fetcher.lock.Lock()
    99  	l.PM.fetcher.nextRequest()
   100  	l.PM.fetcher.lock.Unlock()
   101  
   102  	if reflect.DeepEqual(f2.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
   103  		t.Fatal("Incorrect hash: second peer has empty chain")
   104  	}
   105  }
   106  
   107  func TestULCShouldNotSyncWithThreePeersOneHaveEmptyChain(t *testing.T) {
   108  	f1 := newFullPeerPair(t, 1, 3)
   109  	f2 := newFullPeerPair(t, 2, 4)
   110  	f3 := newFullPeerPair(t, 3, 0)
   111  
   112  	l := newLightPeer(t, []string{f1.Node.String(), f2.Node.String(), f3.Node.String()}, 60)
   113  	_, _, err := connectPeers(f1, l, 2)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  	_, _, err = connectPeers(f2, l, 2)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  	_, _, err = connectPeers(f3, l, 2)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	l.PM.fetcher.lock.Lock()
   126  	l.PM.fetcher.nextRequest()
   127  	l.PM.fetcher.lock.Unlock()
   128  
   129  	if !reflect.DeepEqual(f1.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
   130  		t.Fatal("Incorrect hash")
   131  	}
   132  }
   133  
   134  type pairPeer struct {
   135  	Name string
   136  	Node *enode.Node
   137  	PM   *ProtocolManager
   138  	Key  *ecdsa.PrivateKey
   139  }
   140  
   141  func connectPeers(full, light pairPeer, version int) (*peer, *peer, error) {
   142  	// Create a message pipe to communicate through
   143  	app, net := p2p.MsgPipe()
   144  
   145  	peerLight := full.PM.newPeer(version, NetworkId, p2p.NewPeer(light.Node.ID(), light.Name, nil), net)
   146  	peerFull := light.PM.newPeer(version, NetworkId, p2p.NewPeer(full.Node.ID(), full.Name, nil), app)
   147  
   148  	// Start the peerLight on a new thread
   149  	errc1 := make(chan error, 1)
   150  	errc2 := make(chan error, 1)
   151  	go func() {
   152  		select {
   153  		case light.PM.newPeerCh <- peerFull:
   154  			errc1 <- light.PM.handle(peerFull)
   155  		case <-light.PM.quitSync:
   156  			errc1 <- p2p.DiscQuitting
   157  		}
   158  	}()
   159  	go func() {
   160  		select {
   161  		case full.PM.newPeerCh <- peerLight:
   162  			errc2 <- full.PM.handle(peerLight)
   163  		case <-full.PM.quitSync:
   164  			errc2 <- p2p.DiscQuitting
   165  		}
   166  	}()
   167  
   168  	select {
   169  	case <-time.After(time.Millisecond * 100):
   170  	case err := <-errc1:
   171  		return nil, nil, fmt.Errorf("peerLight handshake error: %v", err)
   172  	case err := <-errc2:
   173  		return nil, nil, fmt.Errorf("peerFull handshake error: %v", err)
   174  	}
   175  
   176  	return peerFull, peerLight, nil
   177  }
   178  
   179  // newFullPeerPair creates node with full sync mode
   180  func newFullPeerPair(t *testing.T, index int, numberOfblocks int) pairPeer {
   181  	db := rawdb.NewMemoryDatabase()
   182  
   183  	pmFull, _ := newTestProtocolManagerMust(t, false, numberOfblocks, nil, nil, nil, db, nil, 0)
   184  
   185  	peerPairFull := pairPeer{
   186  		Name: "full node",
   187  		PM:   pmFull,
   188  	}
   189  	key, err := crypto.GenerateKey()
   190  	if err != nil {
   191  		t.Fatal("generate key err:", err)
   192  	}
   193  	peerPairFull.Key = key
   194  	peerPairFull.Node = enode.NewV4(&key.PublicKey, net.ParseIP("127.0.0.1"), 35000, 35000)
   195  	return peerPairFull
   196  }
   197  
   198  // newLightPeer creates node with light sync mode
   199  func newLightPeer(t *testing.T, ulcServers []string, ulcFraction int) pairPeer {
   200  	peers := newPeerSet()
   201  	dist := newRequestDistributor(peers, make(chan struct{}), &mclock.System{})
   202  	rm := newRetrieveManager(peers, dist, nil)
   203  	ldb := rawdb.NewMemoryDatabase()
   204  
   205  	odr := NewLesOdr(ldb, light.DefaultClientIndexerConfig, rm)
   206  
   207  	pmLight, _ := newTestProtocolManagerMust(t, true, 0, odr, nil, peers, ldb, ulcServers, ulcFraction)
   208  	peerPairLight := pairPeer{
   209  		Name: "ulc node",
   210  		PM:   pmLight,
   211  	}
   212  	key, err := crypto.GenerateKey()
   213  	if err != nil {
   214  		t.Fatal("generate key err:", err)
   215  	}
   216  	peerPairLight.Key = key
   217  	peerPairLight.Node = enode.NewV4(&key.PublicKey, net.IP{}, 35000, 35000)
   218  	return peerPairLight
   219  }