github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/testbackend_test.go (about) 1 // Copyright 2017 AMIS Technologies 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 core 18 19 import ( 20 "crypto/ecdsa" 21 "github.com/ethereum/go-ethereum/p2p/discover" 22 "math/big" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/consensus/podc" 26 "github.com/ethereum/go-ethereum/consensus/podc/validator" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/ethdb" 29 "github.com/ethereum/go-ethereum/event" 30 elog "github.com/ethereum/go-ethereum/log" 31 ) 32 33 var testLogger = elog.New() 34 35 type testSystemBackend struct { 36 id uint64 37 sys *testSystem 38 39 engine Engine 40 peers podc.ValidatorSet 41 events *event.TypeMux 42 43 commitMsgs []podc.Proposal 44 committedSeals [][]byte 45 sentMsgs [][]byte // store the message when Send is called by core 46 47 address common.Address 48 db ethdb.Database 49 } 50 51 // ============================================== 52 // 53 // define the functions that needs to be provided for Istanbul. 54 55 func (self *testSystemBackend) Address() common.Address { 56 return self.address 57 } 58 59 // Peers returns all connected peers 60 func (self *testSystemBackend) Validators(proposal podc.Proposal) podc.ValidatorSet { 61 return self.peers 62 } 63 64 func (self *testSystemBackend) EventMux() *event.TypeMux { 65 return self.events 66 } 67 68 func (self *testSystemBackend) Send(message []byte, target common.Address) error { 69 testLogger.Info("enqueuing a message...", "address", self.Address()) 70 self.sentMsgs = append(self.sentMsgs, message) 71 self.sys.queuedMessage <- podc.MessageEvent{ 72 Payload: message, 73 } 74 return nil 75 } 76 77 func (self *testSystemBackend) Broadcast(valSet podc.ValidatorSet, message []byte) error { 78 testLogger.Info("enqueuing a message...", "address", self.Address()) 79 self.sentMsgs = append(self.sentMsgs, message) 80 self.sys.queuedMessage <- podc.MessageEvent{ 81 Payload: message, 82 } 83 return nil 84 } 85 86 87 // Multicast sends a message to specific targets 88 func (self *testSystemBackend) Multicast( payload []byte, targets []common.Address ) error { 89 testLogger.Info("enqueuing a message...", "address", self.Address()) 90 self.sentMsgs = append(self.sentMsgs, payload) 91 self.sys.queuedMessage <- podc.MessageEvent{ 92 Payload: payload, 93 } 94 return nil 95 } 96 //end 97 98 99 func (self *testSystemBackend) NextRound() error { 100 testLogger.Warn("nothing to happen") 101 return nil 102 } 103 104 func (self *testSystemBackend) Commit(proposal podc.Proposal, seals []byte) error { 105 testLogger.Info("commit message", "address", self.Address()) 106 self.commitMsgs = append(self.commitMsgs, proposal) 107 self.committedSeals = append(self.committedSeals, seals) 108 109 // fake new head events 110 go self.events.Post(podc.FinalCommittedEvent{ 111 Proposal: proposal, 112 }) 113 return nil 114 } 115 116 func (self *testSystemBackend) Verify(proposal podc.Proposal) error { 117 return nil 118 } 119 120 func (self *testSystemBackend) Sign(data []byte) ([]byte, error) { 121 testLogger.Warn("not sign any data") 122 return data, nil 123 } 124 125 func (self *testSystemBackend) CheckSignature([]byte, common.Address, []byte) error { 126 return nil 127 } 128 129 func (self *testSystemBackend) CheckValidatorSignature(data []byte, sig []byte) (common.Address, error) { 130 return common.Address{}, nil 131 } 132 133 func (self *testSystemBackend) Hash(b interface{}) common.Hash { 134 return common.StringToHash("Test") 135 } 136 137 func (self *testSystemBackend) NewRequest(request podc.Proposal) { 138 go self.events.Post(podc.RequestEvent{ 139 Proposal: request, 140 }) 141 } 142 143 // define the struct that need to be provided for integration tests. 144 145 type testSystem struct { 146 backends []*testSystemBackend 147 148 queuedMessage chan podc.MessageEvent 149 quit chan struct{} 150 } 151 152 func newTestSystem(n uint64) *testSystem { 153 testLogger.SetHandler(elog.StdoutHandler) 154 return &testSystem{ 155 backends: make([]*testSystemBackend, n), 156 157 queuedMessage: make(chan podc.MessageEvent), 158 quit: make(chan struct{}), 159 } 160 } 161 162 func generateValidators(n int) []common.Address { 163 vals := make([]common.Address, 0) 164 for i := 0; i < n; i++ { 165 privateKey, _ := crypto.GenerateKey() 166 vals = append(vals, crypto.PubkeyToAddress(privateKey.PublicKey)) 167 } 168 return vals 169 } 170 171 func newTestValidatorSet(n int) podc.ValidatorSet { 172 return validator.NewSet(generateValidators(n), podc.RoundRobin) 173 } 174 175 // FIXME: int64 is needed for N and F 176 func NewTestSystemWithBackend(n, f uint64) *testSystem { 177 testLogger.SetHandler(elog.StdoutHandler) 178 179 addrs := generateValidators(int(n)) 180 sys := newTestSystem(n) 181 config := podc.DefaultConfig 182 183 for i := uint64(0); i < n; i++ { 184 vset := validator.NewSet(addrs, podc.RoundRobin) 185 backend := sys.NewBackend(i) 186 backend.peers = vset 187 backend.address = vset.GetByIndex(i).Address() 188 189 core := New(backend, config).(*core) 190 core.state = StateAcceptRequest 191 core.lastProposer = common.Address{} 192 core.current = newRoundState(&podc.View{ 193 Round: big.NewInt(0), 194 Sequence: big.NewInt(1), 195 }, vset) 196 core.logger = testLogger 197 core.validateFn = backend.CheckValidatorSignature 198 199 backend.engine = core 200 } 201 202 return sys 203 } 204 205 // listen will consume messages from queue and deliver a message to core 206 func (t *testSystem) listen() { 207 for { 208 select { 209 case <-t.quit: 210 return 211 case queuedMessage := <-t.queuedMessage: 212 testLogger.Info("consuming a queue message...") 213 for _, backend := range t.backends { 214 go backend.EventMux().Post(queuedMessage) 215 } 216 } 217 } 218 } 219 220 // Run will start system components based on given flag, and returns a closer 221 // function that caller can control lifecycle 222 // 223 // Given a true for core if you want to initialize core engine. 224 func (t *testSystem) Run(core bool) func() { 225 226 var qman []*discover.Node 227 for _, b := range t.backends { 228 if core { 229 b.engine.Start(common.Big0, common.Address{}, nil, qman) // start PoDC core 230 } 231 } 232 233 go t.listen() 234 closer := func() { t.stop(core) } 235 return closer 236 } 237 238 func (t *testSystem) stop(core bool) { 239 close(t.quit) 240 241 for _, b := range t.backends { 242 if core { 243 b.engine.Stop() 244 } 245 } 246 } 247 248 func (t *testSystem) NewBackend(id uint64) *testSystemBackend { 249 // assume always success 250 ethDB, _ := ethdb.NewMemDatabase() 251 backend := &testSystemBackend{ 252 id: id, 253 sys: t, 254 events: new(event.TypeMux), 255 db: ethDB, 256 } 257 258 t.backends[id] = backend 259 return backend 260 } 261 262 // helper functions. 263 264 func getPublicKeyAddress(privateKey *ecdsa.PrivateKey) common.Address { 265 return crypto.PubkeyToAddress(privateKey.PublicKey) 266 }