handler_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2015 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. package backend
  17. import (
  18. "bytes"
  19. "io/ioutil"
  20. "math/big"
  21. "testing"
  22. "time"
  23. "github.com/ethereum/go-ethereum/common"
  24. "github.com/ethereum/go-ethereum/consensus/istanbul"
  25. "github.com/ethereum/go-ethereum/core/types"
  26. "github.com/ethereum/go-ethereum/p2p"
  27. "github.com/ethereum/go-ethereum/rlp"
  28. "github.com/ethereum/go-ethereum/trie"
  29. lru "github.com/hashicorp/golang-lru"
  30. )
  31. func TestIstanbulMessage(t *testing.T) {
  32. _, backend := newBlockChain(1, nil)
  33. defer backend.Stop()
  34. // generate one msg
  35. data := []byte("data1")
  36. hash := istanbul.RLPHash(data)
  37. msg := makeMsg(istanbulMsg, data)
  38. addr := common.StringToAddress("address")
  39. // 1. this message should not be in cache
  40. // for peers
  41. if _, ok := backend.recentMessages.Get(addr); ok {
  42. t.Fatalf("the cache of messages for this peer should be nil")
  43. }
  44. // for self
  45. if _, ok := backend.knownMessages.Get(hash); ok {
  46. t.Fatalf("the cache of messages should be nil")
  47. }
  48. // 2. this message should be in cache after we handle it
  49. _, err := backend.HandleMsg(addr, msg)
  50. if err != nil {
  51. t.Fatalf("handle message failed: %v", err)
  52. }
  53. // for peers
  54. if ms, ok := backend.recentMessages.Get(addr); ms == nil || !ok {
  55. t.Fatalf("the cache of messages for this peer cannot be nil")
  56. } else if m, ok := ms.(*lru.ARCCache); !ok {
  57. t.Fatalf("the cache of messages for this peer cannot be casted")
  58. } else if _, ok := m.Get(hash); !ok {
  59. t.Fatalf("the cache of messages for this peer cannot be found")
  60. }
  61. // for self
  62. if _, ok := backend.knownMessages.Get(hash); !ok {
  63. t.Fatalf("the cache of messages cannot be found")
  64. }
  65. }
  66. func makeMsg(msgcode uint64, data interface{}) p2p.Msg {
  67. size, r, _ := rlp.EncodeToReader(data)
  68. return p2p.Msg{Code: msgcode, Size: uint32(size), Payload: r}
  69. }
  70. func tryUntilMessageIsHandled(backend *Backend, arbitraryAddress common.Address, arbitraryP2PMessage p2p.Msg) (handled bool, err error) {
  71. for i := 0; i < 5; i++ { // make 5 tries if a little wait
  72. handled, err = backend.HandleMsg(arbitraryAddress, arbitraryP2PMessage)
  73. if handled && err == nil {
  74. return
  75. }
  76. time.Sleep(2 * time.Millisecond)
  77. }
  78. return
  79. }
  80. func TestHandleNewBlockMessage_whenTypical(t *testing.T) {
  81. _, backend := newBlockChain(1, nil)
  82. defer backend.Stop()
  83. arbitraryAddress := common.StringToAddress("arbitrary")
  84. arbitraryBlock, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, false)
  85. postAndWait(backend, arbitraryBlock, t)
  86. handled, err := tryUntilMessageIsHandled(backend, arbitraryAddress, arbitraryP2PMessage)
  87. if err != nil {
  88. t.Errorf("expected message being handled successfully but got %s", err)
  89. }
  90. if !handled {
  91. t.Errorf("expected message being handled but not")
  92. }
  93. if _, err := ioutil.ReadAll(arbitraryP2PMessage.Payload); err != nil {
  94. t.Errorf("expected p2p message payload is restored")
  95. }
  96. }
  97. func TestHandleNewBlockMessage_whenNotAProposedBlock(t *testing.T) {
  98. _, backend := newBlockChain(1, nil)
  99. defer backend.Stop()
  100. arbitraryAddress := common.StringToAddress("arbitrary")
  101. _, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, false)
  102. postAndWait(backend, types.NewBlock(&types.Header{
  103. Number: big.NewInt(1),
  104. Root: common.StringToHash("someroot"),
  105. GasLimit: 1,
  106. MixDigest: types.IstanbulDigest,
  107. }, nil, nil, nil, new(trie.Trie)), t)
  108. handled, err := tryUntilMessageIsHandled(backend, arbitraryAddress, arbitraryP2PMessage)
  109. if err != nil {
  110. t.Errorf("expected message being handled successfully but got %s", err)
  111. }
  112. if handled {
  113. t.Errorf("expected message not being handled")
  114. }
  115. if _, err := ioutil.ReadAll(arbitraryP2PMessage.Payload); err != nil {
  116. t.Errorf("expected p2p message payload is restored")
  117. }
  118. }
  119. func TestHandleNewBlockMessage_whenFailToDecode(t *testing.T) {
  120. _, backend := newBlockChain(1, nil)
  121. defer backend.Stop()
  122. arbitraryAddress := common.StringToAddress("arbitrary")
  123. _, arbitraryP2PMessage := buildArbitraryP2PNewBlockMessage(t, true)
  124. postAndWait(backend, types.NewBlock(&types.Header{
  125. Number: big.NewInt(1),
  126. GasLimit: 1,
  127. MixDigest: types.IstanbulDigest,
  128. }, nil, nil, nil, new(trie.Trie)), t)
  129. handled, err := tryUntilMessageIsHandled(backend, arbitraryAddress, arbitraryP2PMessage)
  130. if err != nil {
  131. t.Errorf("expected message being handled successfully but got %s", err)
  132. }
  133. if handled {
  134. t.Errorf("expected message not being handled")
  135. }
  136. if _, err := ioutil.ReadAll(arbitraryP2PMessage.Payload); err != nil {
  137. t.Errorf("expected p2p message payload is restored")
  138. }
  139. }
  140. func postAndWait(backend *Backend, block *types.Block, t *testing.T) {
  141. eventSub := backend.EventMux().Subscribe(istanbul.RequestEvent{})
  142. defer eventSub.Unsubscribe()
  143. stop := make(chan struct{}, 1)
  144. eventLoop := func() {
  145. <-eventSub.Chan()
  146. stop <- struct{}{}
  147. }
  148. go eventLoop()
  149. if err := backend.EventMux().Post(istanbul.RequestEvent{
  150. Proposal: block,
  151. }); err != nil {
  152. t.Fatalf("%s", err)
  153. }
  154. <-stop
  155. }
  156. func buildArbitraryP2PNewBlockMessage(t *testing.T, invalidMsg bool) (*types.Block, p2p.Msg) {
  157. arbitraryBlock := types.NewBlock(&types.Header{
  158. Number: big.NewInt(1),
  159. GasLimit: 0,
  160. MixDigest: types.IstanbulDigest,
  161. }, nil, nil, nil, new(trie.Trie))
  162. request := []interface{}{&arbitraryBlock, big.NewInt(1)}
  163. if invalidMsg {
  164. request = []interface{}{"invalid msg"}
  165. }
  166. size, r, err := rlp.EncodeToReader(request)
  167. if err != nil {
  168. t.Fatalf("can't encode due to %s", err)
  169. }
  170. payload, err := ioutil.ReadAll(r)
  171. if err != nil {
  172. t.Fatalf("can't read payload due to %s", err)
  173. }
  174. arbitraryP2PMessage := p2p.Msg{Code: 0x07, Size: uint32(size), Payload: bytes.NewReader(payload)}
  175. return arbitraryBlock, arbitraryP2PMessage
  176. }