github.com/hardtosaygoodbye/go-ethereum@v1.10.16-0.20220122011429-97003b9e6c15/les/ulc_test.go (about) 1 // Copyright 2018 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/rand" 21 "fmt" 22 "net" 23 "sync/atomic" 24 "testing" 25 "time" 26 27 "github.com/hardtosaygoodbye/go-ethereum/crypto" 28 "github.com/hardtosaygoodbye/go-ethereum/p2p" 29 "github.com/hardtosaygoodbye/go-ethereum/p2p/enode" 30 ) 31 32 func TestULCAnnounceThresholdLes2(t *testing.T) { testULCAnnounceThreshold(t, 2) } 33 func TestULCAnnounceThresholdLes3(t *testing.T) { testULCAnnounceThreshold(t, 3) } 34 35 func testULCAnnounceThreshold(t *testing.T, protocol int) { 36 // todo figure out why it takes fetcher so longer to fetcher the announced header. 37 t.Skip("Sometimes it can failed") 38 var cases = []struct { 39 height []int 40 threshold int 41 expect uint64 42 }{ 43 {[]int{1}, 100, 1}, 44 {[]int{0, 0, 0}, 100, 0}, 45 {[]int{1, 2, 3}, 30, 3}, 46 {[]int{1, 2, 3}, 60, 2}, 47 {[]int{3, 2, 1}, 67, 1}, 48 {[]int{3, 2, 1}, 100, 1}, 49 } 50 for _, testcase := range cases { 51 var ( 52 servers []*testServer 53 teardowns []func() 54 nodes []*enode.Node 55 ids []string 56 ) 57 for i := 0; i < len(testcase.height); i++ { 58 s, n, teardown := newTestServerPeer(t, 0, protocol) 59 60 servers = append(servers, s) 61 nodes = append(nodes, n) 62 teardowns = append(teardowns, teardown) 63 ids = append(ids, n.String()) 64 } 65 c, teardown := newTestLightPeer(t, protocol, ids, testcase.threshold) 66 67 // Connect all servers. 68 for i := 0; i < len(servers); i++ { 69 connect(servers[i].handler, nodes[i].ID(), c.handler, protocol, false) 70 } 71 for i := 0; i < len(servers); i++ { 72 for j := 0; j < testcase.height[i]; j++ { 73 servers[i].backend.Commit() 74 } 75 } 76 time.Sleep(1500 * time.Millisecond) // Ensure the fetcher has done its work. 77 head := c.handler.backend.blockchain.CurrentHeader().Number.Uint64() 78 if head != testcase.expect { 79 t.Fatalf("chain height mismatch, want %d, got %d", testcase.expect, head) 80 } 81 82 // Release all servers and client resources. 83 teardown() 84 for i := 0; i < len(teardowns); i++ { 85 teardowns[i]() 86 } 87 } 88 } 89 90 func connect(server *serverHandler, serverId enode.ID, client *clientHandler, protocol int, noInitAnnounce bool) (*serverPeer, *clientPeer, error) { 91 // Create a message pipe to communicate through 92 app, net := p2p.MsgPipe() 93 94 var id enode.ID 95 rand.Read(id[:]) 96 97 peer1 := newServerPeer(protocol, NetworkId, true, p2p.NewPeer(serverId, "", nil), net) // Mark server as trusted 98 peer2 := newClientPeer(protocol, NetworkId, p2p.NewPeer(id, "", nil), app) 99 100 // Start the peerLight on a new thread 101 errc1 := make(chan error, 1) 102 errc2 := make(chan error, 1) 103 go func() { 104 select { 105 case <-server.closeCh: 106 errc1 <- p2p.DiscQuitting 107 case errc1 <- server.handle(peer2): 108 } 109 }() 110 go func() { 111 select { 112 case <-client.closeCh: 113 errc1 <- p2p.DiscQuitting 114 case errc1 <- client.handle(peer1, noInitAnnounce): 115 } 116 }() 117 // Ensure the connection is established or exits when any error occurs 118 for { 119 select { 120 case err := <-errc1: 121 return nil, nil, fmt.Errorf("failed to establish protocol connection %v", err) 122 case err := <-errc2: 123 return nil, nil, fmt.Errorf("failed to establish protocol connection %v", err) 124 default: 125 } 126 if atomic.LoadUint32(&peer1.serving) == 1 && atomic.LoadUint32(&peer2.serving) == 1 { 127 break 128 } 129 time.Sleep(50 * time.Millisecond) 130 } 131 return peer1, peer2, nil 132 } 133 134 // newTestServerPeer creates server peer. 135 func newTestServerPeer(t *testing.T, blocks int, protocol int) (*testServer, *enode.Node, func()) { 136 netconfig := testnetConfig{ 137 blocks: blocks, 138 protocol: protocol, 139 nopruning: true, 140 } 141 s, _, teardown := newClientServerEnv(t, netconfig) 142 key, err := crypto.GenerateKey() 143 if err != nil { 144 t.Fatal("generate key err:", err) 145 } 146 s.handler.server.privateKey = key 147 n := enode.NewV4(&key.PublicKey, net.ParseIP("127.0.0.1"), 35000, 35000) 148 return s, n, teardown 149 } 150 151 // newTestLightPeer creates node with light sync mode 152 func newTestLightPeer(t *testing.T, protocol int, ulcServers []string, ulcFraction int) (*testClient, func()) { 153 netconfig := testnetConfig{ 154 protocol: protocol, 155 ulcServers: ulcServers, 156 ulcFraction: ulcFraction, 157 nopruning: true, 158 } 159 _, c, teardown := newClientServerEnv(t, netconfig) 160 return c, teardown 161 }