ulc_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package les
  2. import (
  3. "crypto/ecdsa"
  4. "fmt"
  5. "math/big"
  6. "net"
  7. "reflect"
  8. "testing"
  9. "time"
  10. "github.com/ethereum/go-ethereum/common/mclock"
  11. "github.com/ethereum/go-ethereum/core"
  12. "github.com/ethereum/go-ethereum/core/rawdb"
  13. "github.com/ethereum/go-ethereum/crypto"
  14. "github.com/ethereum/go-ethereum/eth"
  15. "github.com/ethereum/go-ethereum/light"
  16. "github.com/ethereum/go-ethereum/p2p"
  17. "github.com/ethereum/go-ethereum/p2p/enode"
  18. )
  19. func TestULCSyncWithOnePeer(t *testing.T) {
  20. f := newFullPeerPair(t, 1, 4, testChainGen)
  21. ulcConfig := &eth.ULCConfig{
  22. MinTrustedFraction: 100,
  23. TrustedServers: []string{f.Node.String()},
  24. }
  25. l := newLightPeer(t, ulcConfig)
  26. if reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
  27. t.Fatal("blocks are equal")
  28. }
  29. _, _, err := connectPeers(f, l, 2)
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. l.PM.fetcher.lock.Lock()
  34. l.PM.fetcher.nextRequest()
  35. l.PM.fetcher.lock.Unlock()
  36. if !reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
  37. t.Fatal("sync doesn't work")
  38. }
  39. }
  40. func TestULCReceiveAnnounce(t *testing.T) {
  41. f := newFullPeerPair(t, 1, 4, testChainGen)
  42. ulcConfig := &eth.ULCConfig{
  43. MinTrustedFraction: 100,
  44. TrustedServers: []string{f.Node.String()},
  45. }
  46. l := newLightPeer(t, ulcConfig)
  47. fPeer, lPeer, err := connectPeers(f, l, 2)
  48. if err != nil {
  49. t.Fatal(err)
  50. }
  51. l.PM.synchronise(fPeer)
  52. //check that the sync is finished correctly
  53. if !reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
  54. t.Fatal("sync doesn't work")
  55. }
  56. l.PM.peers.lock.Lock()
  57. if len(l.PM.peers.peers) == 0 {
  58. t.Fatal("peer list should not be empty")
  59. }
  60. l.PM.peers.lock.Unlock()
  61. time.Sleep(time.Second)
  62. //send a signed announce message(payload doesn't matter)
  63. td := f.PM.blockchain.GetTd(l.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Number.Uint64())
  64. announce := announceData{
  65. Number: l.PM.blockchain.CurrentHeader().Number.Uint64() + 1,
  66. Td: td.Add(td, big.NewInt(1)),
  67. }
  68. announce.sign(f.Key)
  69. lPeer.SendAnnounce(announce)
  70. }
  71. func TestULCShouldNotSyncWithTwoPeersOneHaveEmptyChain(t *testing.T) {
  72. f1 := newFullPeerPair(t, 1, 4, testChainGen)
  73. f2 := newFullPeerPair(t, 2, 0, nil)
  74. ulcConf := &ulc{minTrustedFraction: 100, trustedKeys: make(map[string]struct{})}
  75. ulcConf.trustedKeys[f1.Node.ID().String()] = struct{}{}
  76. ulcConf.trustedKeys[f2.Node.ID().String()] = struct{}{}
  77. ulcConfig := &eth.ULCConfig{
  78. MinTrustedFraction: 100,
  79. TrustedServers: []string{f1.Node.String(), f2.Node.String()},
  80. }
  81. l := newLightPeer(t, ulcConfig)
  82. l.PM.ulc.minTrustedFraction = 100
  83. _, _, err := connectPeers(f1, l, 2)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. _, _, err = connectPeers(f2, l, 2)
  88. if err != nil {
  89. t.Fatal(err)
  90. }
  91. l.PM.fetcher.lock.Lock()
  92. l.PM.fetcher.nextRequest()
  93. l.PM.fetcher.lock.Unlock()
  94. if reflect.DeepEqual(f2.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
  95. t.Fatal("Incorrect hash: second peer has empty chain")
  96. }
  97. }
  98. func TestULCShouldNotSyncWithThreePeersOneHaveEmptyChain(t *testing.T) {
  99. f1 := newFullPeerPair(t, 1, 3, testChainGen)
  100. f2 := newFullPeerPair(t, 2, 4, testChainGen)
  101. f3 := newFullPeerPair(t, 3, 0, nil)
  102. ulcConfig := &eth.ULCConfig{
  103. MinTrustedFraction: 60,
  104. TrustedServers: []string{f1.Node.String(), f2.Node.String(), f3.Node.String()},
  105. }
  106. l := newLightPeer(t, ulcConfig)
  107. _, _, err := connectPeers(f1, l, 2)
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. _, _, err = connectPeers(f2, l, 2)
  112. if err != nil {
  113. t.Fatal(err)
  114. }
  115. _, _, err = connectPeers(f3, l, 2)
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. l.PM.fetcher.lock.Lock()
  120. l.PM.fetcher.nextRequest()
  121. l.PM.fetcher.lock.Unlock()
  122. if !reflect.DeepEqual(f1.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
  123. t.Fatal("Incorrect hash")
  124. }
  125. }
  126. type pairPeer struct {
  127. Name string
  128. Node *enode.Node
  129. PM *ProtocolManager
  130. Key *ecdsa.PrivateKey
  131. }
  132. func connectPeers(full, light pairPeer, version int) (*peer, *peer, error) {
  133. // Create a message pipe to communicate through
  134. app, net := p2p.MsgPipe()
  135. peerLight := full.PM.newPeer(version, NetworkId, p2p.NewPeer(light.Node.ID(), light.Name, nil), net)
  136. peerFull := light.PM.newPeer(version, NetworkId, p2p.NewPeer(full.Node.ID(), full.Name, nil), app)
  137. // Start the peerLight on a new thread
  138. errc1 := make(chan error, 1)
  139. errc2 := make(chan error, 1)
  140. go func() {
  141. select {
  142. case light.PM.newPeerCh <- peerFull:
  143. errc1 <- light.PM.handle(peerFull)
  144. case <-light.PM.quitSync:
  145. errc1 <- p2p.DiscQuitting
  146. }
  147. }()
  148. go func() {
  149. select {
  150. case full.PM.newPeerCh <- peerLight:
  151. errc2 <- full.PM.handle(peerLight)
  152. case <-full.PM.quitSync:
  153. errc2 <- p2p.DiscQuitting
  154. }
  155. }()
  156. select {
  157. case <-time.After(time.Millisecond * 100):
  158. case err := <-errc1:
  159. return nil, nil, fmt.Errorf("peerLight handshake error: %v", err)
  160. case err := <-errc2:
  161. return nil, nil, fmt.Errorf("peerFull handshake error: %v", err)
  162. }
  163. return peerFull, peerLight, nil
  164. }
  165. // newFullPeerPair creates node with full sync mode
  166. func newFullPeerPair(t *testing.T, index int, numberOfblocks int, chainGen func(int, *core.BlockGen)) pairPeer {
  167. db := rawdb.NewMemoryDatabase()
  168. pmFull := newTestProtocolManagerMust(t, false, numberOfblocks, chainGen, nil, nil, db, nil)
  169. peerPairFull := pairPeer{
  170. Name: "full node",
  171. PM: pmFull,
  172. }
  173. key, err := crypto.GenerateKey()
  174. if err != nil {
  175. t.Fatal("generate key err:", err)
  176. }
  177. peerPairFull.Key = key
  178. peerPairFull.Node = enode.NewV4(&key.PublicKey, net.ParseIP("127.0.0.1"), 35000, 35000)
  179. return peerPairFull
  180. }
  181. // newLightPeer creates node with light sync mode
  182. func newLightPeer(t *testing.T, ulcConfig *eth.ULCConfig) pairPeer {
  183. peers := newPeerSet()
  184. dist := newRequestDistributor(peers, make(chan struct{}), &mclock.System{})
  185. rm := newRetrieveManager(peers, dist, nil)
  186. ldb := rawdb.NewMemoryDatabase()
  187. odr := NewLesOdr(ldb, light.DefaultClientIndexerConfig, rm)
  188. pmLight := newTestProtocolManagerMust(t, true, 0, nil, odr, peers, ldb, ulcConfig)
  189. peerPairLight := pairPeer{
  190. Name: "ulc node",
  191. PM: pmLight,
  192. }
  193. key, err := crypto.GenerateKey()
  194. if err != nil {
  195. t.Fatal("generate key err:", err)
  196. }
  197. peerPairLight.Key = key
  198. peerPairLight.Node = enode.NewV4(&key.PublicKey, net.IP{}, 35000, 35000)
  199. return peerPairLight
  200. }