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