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