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