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