protocol_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. package eth
  2. /*
  3. TODO All of these tests need to be re-written
  4. var logsys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel))
  5. var ini = false
  6. func logInit() {
  7. if !ini {
  8. ethlogger.AddLogSystem(logsys)
  9. ini = true
  10. }
  11. }
  12. type testTxPool struct {
  13. getTransactions func() []*types.Transaction
  14. addTransactions func(txs []*types.Transaction)
  15. }
  16. type testChainManager struct {
  17. getBlockHashes func(hash common.Hash, amount uint64) (hashes []common.Hash)
  18. getBlock func(hash common.Hash) *types.Block
  19. status func() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
  20. }
  21. type testBlockPool struct {
  22. addBlockHashes func(next func() (common.Hash, bool), peerId string)
  23. addBlock func(block *types.Block, peerId string) (err error)
  24. addPeer func(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool, suspended bool)
  25. removePeer func(peerId string)
  26. }
  27. func (self *testTxPool) AddTransactions(txs []*types.Transaction) {
  28. if self.addTransactions != nil {
  29. self.addTransactions(txs)
  30. }
  31. }
  32. func (self *testTxPool) GetTransactions() types.Transactions { return nil }
  33. func (self *testChainManager) GetBlockHashesFromHash(hash common.Hash, amount uint64) (hashes []common.Hash) {
  34. if self.getBlockHashes != nil {
  35. hashes = self.getBlockHashes(hash, amount)
  36. }
  37. return
  38. }
  39. func (self *testChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
  40. if self.status != nil {
  41. td, currentBlock, genesisBlock = self.status()
  42. } else {
  43. td = common.Big1
  44. currentBlock = common.Hash{1}
  45. genesisBlock = common.Hash{2}
  46. }
  47. return
  48. }
  49. func (self *testChainManager) GetBlock(hash common.Hash) (block *types.Block) {
  50. if self.getBlock != nil {
  51. block = self.getBlock(hash)
  52. }
  53. return
  54. }
  55. func (self *testBlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId string) {
  56. if self.addBlockHashes != nil {
  57. self.addBlockHashes(next, peerId)
  58. }
  59. }
  60. func (self *testBlockPool) AddBlock(block *types.Block, peerId string) {
  61. if self.addBlock != nil {
  62. self.addBlock(block, peerId)
  63. }
  64. }
  65. func (self *testBlockPool) AddPeer(td *big.Int, currentBlock common.Hash, peerId string, requestBlockHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool, suspended bool) {
  66. if self.addPeer != nil {
  67. best, suspended = self.addPeer(td, currentBlock, peerId, requestBlockHashes, requestBlocks, peerError)
  68. }
  69. return
  70. }
  71. func (self *testBlockPool) RemovePeer(peerId string) {
  72. if self.removePeer != nil {
  73. self.removePeer(peerId)
  74. }
  75. }
  76. func testPeer() *p2p.Peer {
  77. var id discover.NodeID
  78. pk := crypto.GenerateNewKeyPair().PublicKey
  79. copy(id[:], pk)
  80. return p2p.NewPeer(id, "test peer", []p2p.Cap{})
  81. }
  82. type ethProtocolTester struct {
  83. p2p.MsgReadWriter // writing to the tester feeds the protocol
  84. quit chan error
  85. pipe *p2p.MsgPipeRW // the protocol read/writes on this end
  86. txPool *testTxPool // txPool
  87. chainManager *testChainManager // chainManager
  88. blockPool *testBlockPool // blockPool
  89. t *testing.T
  90. }
  91. func newEth(t *testing.T) *ethProtocolTester {
  92. p1, p2 := p2p.MsgPipe()
  93. return &ethProtocolTester{
  94. MsgReadWriter: p1,
  95. quit: make(chan error, 1),
  96. pipe: p2,
  97. txPool: &testTxPool{},
  98. chainManager: &testChainManager{},
  99. blockPool: &testBlockPool{},
  100. t: t,
  101. }
  102. }
  103. func (self *ethProtocolTester) reset() {
  104. self.pipe.Close()
  105. p1, p2 := p2p.MsgPipe()
  106. self.MsgReadWriter = p1
  107. self.pipe = p2
  108. self.quit = make(chan error, 1)
  109. }
  110. func (self *ethProtocolTester) checkError(expCode int, delay time.Duration) (err error) {
  111. var timer = time.After(delay)
  112. select {
  113. case err = <-self.quit:
  114. case <-timer:
  115. self.t.Errorf("no error after %v, expected %v", delay, expCode)
  116. return
  117. }
  118. perr, ok := err.(*errs.Error)
  119. if ok && perr != nil {
  120. if code := perr.Code; code != expCode {
  121. self.t.Errorf("expected protocol error (code %v), got %v (%v)", expCode, code, err)
  122. }
  123. } else {
  124. self.t.Errorf("expected protocol error (code %v), got %v", expCode, err)
  125. }
  126. return
  127. }
  128. func (self *ethProtocolTester) run() {
  129. err := runEthProtocol(ProtocolVersion, NetworkId, self.txPool, self.chainManager, self.blockPool, testPeer(), self.pipe)
  130. self.quit <- err
  131. }
  132. func (self *ethProtocolTester) handshake(t *testing.T, mock bool) {
  133. td, currentBlock, genesis := self.chainManager.Status()
  134. // first outgoing msg should be StatusMsg.
  135. err := p2p.ExpectMsg(self, StatusMsg, &statusMsgData{
  136. ProtocolVersion: ProtocolVersion,
  137. NetworkId: NetworkId,
  138. TD: td,
  139. CurrentBlock: currentBlock,
  140. GenesisBlock: genesis,
  141. })
  142. if err != nil {
  143. t.Fatalf("incorrect outgoing status: %v", err)
  144. }
  145. if mock {
  146. go p2p.Send(self, StatusMsg, &statusMsgData{ProtocolVersion, NetworkId, td, currentBlock, genesis})
  147. }
  148. }
  149. func TestStatusMsgErrors(t *testing.T) {
  150. logInit()
  151. eth := newEth(t)
  152. go eth.run()
  153. td, currentBlock, genesis := eth.chainManager.Status()
  154. tests := []struct {
  155. code uint64
  156. data interface{}
  157. wantErrorCode int
  158. }{
  159. {
  160. code: TxMsg, data: []interface{}{},
  161. wantErrorCode: ErrNoStatusMsg,
  162. },
  163. {
  164. code: StatusMsg, data: statusMsgData{10, NetworkId, td, currentBlock, genesis},
  165. wantErrorCode: ErrProtocolVersionMismatch,
  166. },
  167. {
  168. code: StatusMsg, data: statusMsgData{ProtocolVersion, 999, td, currentBlock, genesis},
  169. wantErrorCode: ErrNetworkIdMismatch,
  170. },
  171. {
  172. code: StatusMsg, data: statusMsgData{ProtocolVersion, NetworkId, td, currentBlock, common.Hash{3}},
  173. wantErrorCode: ErrGenesisBlockMismatch,
  174. },
  175. }
  176. for _, test := range tests {
  177. eth.handshake(t, false)
  178. // the send call might hang until reset because
  179. // the protocol might not read the payload.
  180. go p2p.Send(eth, test.code, test.data)
  181. eth.checkError(test.wantErrorCode, 1*time.Second)
  182. eth.reset()
  183. go eth.run()
  184. }
  185. }
  186. func TestNewBlockMsg(t *testing.T) {
  187. // logInit()
  188. eth := newEth(t)
  189. var disconnected bool
  190. eth.blockPool.removePeer = func(peerId string) {
  191. disconnected = true
  192. }
  193. go eth.run()
  194. eth.handshake(t, true)
  195. err := p2p.ExpectMsg(eth, TxMsg, []interface{}{})
  196. if err != nil {
  197. t.Errorf("transactions expected, got %v", err)
  198. }
  199. var tds = make(chan *big.Int)
  200. eth.blockPool.addPeer = func(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool, suspended bool) {
  201. tds <- td
  202. return
  203. }
  204. var delay = 1 * time.Second
  205. // eth.reset()
  206. block := types.NewBlock(common.Hash{1}, common.Address{1}, common.Hash{1}, common.Big1, 1, []byte("extra"))
  207. go p2p.Send(eth, NewBlockMsg, &newBlockMsgData{Block: block})
  208. timer := time.After(delay)
  209. select {
  210. case td := <-tds:
  211. if td.Cmp(common.Big0) != 0 {
  212. t.Errorf("incorrect td %v, expected %v", td, common.Big0)
  213. }
  214. case <-timer:
  215. t.Errorf("no td recorded after %v", delay)
  216. return
  217. case err := <-eth.quit:
  218. t.Errorf("no error expected, got %v", err)
  219. return
  220. }
  221. go p2p.Send(eth, NewBlockMsg, &newBlockMsgData{block, common.Big2})
  222. timer = time.After(delay)
  223. select {
  224. case td := <-tds:
  225. if td.Cmp(common.Big2) != 0 {
  226. t.Errorf("incorrect td %v, expected %v", td, common.Big2)
  227. }
  228. case <-timer:
  229. t.Errorf("no td recorded after %v", delay)
  230. return
  231. case err := <-eth.quit:
  232. t.Errorf("no error expected, got %v", err)
  233. return
  234. }
  235. go p2p.Send(eth, NewBlockMsg, []interface{}{})
  236. // Block.DecodeRLP: validation failed: header is nil
  237. eth.checkError(ErrDecode, delay)
  238. }
  239. func TestBlockMsg(t *testing.T) {
  240. // logInit()
  241. eth := newEth(t)
  242. blocks := make(chan *types.Block)
  243. eth.blockPool.addBlock = func(block *types.Block, peerId string) (err error) {
  244. blocks <- block
  245. return
  246. }
  247. var disconnected bool
  248. eth.blockPool.removePeer = func(peerId string) {
  249. disconnected = true
  250. }
  251. go eth.run()
  252. eth.handshake(t, true)
  253. err := p2p.ExpectMsg(eth, TxMsg, []interface{}{})
  254. if err != nil {
  255. t.Errorf("transactions expected, got %v", err)
  256. }
  257. var delay = 3 * time.Second
  258. // eth.reset()
  259. newblock := func(i int64) *types.Block {
  260. return types.NewBlock(common.Hash{byte(i)}, common.Address{byte(i)}, common.Hash{byte(i)}, big.NewInt(i), uint64(i), []byte{byte(i)})
  261. }
  262. b := newblock(0)
  263. b.Header().Difficulty = nil // check if nil as *big.Int decodes as 0
  264. go p2p.Send(eth, BlocksMsg, types.Blocks{b, newblock(1), newblock(2)})
  265. timer := time.After(delay)
  266. for i := int64(0); i < 3; i++ {
  267. select {
  268. case block := <-blocks:
  269. if (block.ParentHash() != common.Hash{byte(i)}) {
  270. t.Errorf("incorrect block %v, expected %v", block.ParentHash(), common.Hash{byte(i)})
  271. }
  272. if block.Difficulty().Cmp(big.NewInt(i)) != 0 {
  273. t.Errorf("incorrect block %v, expected %v", block.Difficulty(), big.NewInt(i))
  274. }
  275. case <-timer:
  276. t.Errorf("no td recorded after %v", delay)
  277. return
  278. case err := <-eth.quit:
  279. t.Errorf("no error expected, got %v", err)
  280. return
  281. }
  282. }
  283. go p2p.Send(eth, BlocksMsg, []interface{}{[]interface{}{}})
  284. eth.checkError(ErrDecode, delay)
  285. if !disconnected {
  286. t.Errorf("peer not disconnected after error")
  287. }
  288. // test empty transaction
  289. eth.reset()
  290. go eth.run()
  291. eth.handshake(t, true)
  292. err = p2p.ExpectMsg(eth, TxMsg, []interface{}{})
  293. if err != nil {
  294. t.Errorf("transactions expected, got %v", err)
  295. }
  296. b = newblock(0)
  297. b.AddTransaction(nil)
  298. go p2p.Send(eth, BlocksMsg, types.Blocks{b})
  299. eth.checkError(ErrDecode, delay)
  300. }
  301. func TestTransactionsMsg(t *testing.T) {
  302. logInit()
  303. eth := newEth(t)
  304. txs := make(chan *types.Transaction)
  305. eth.txPool.addTransactions = func(t []*types.Transaction) {
  306. for _, tx := range t {
  307. txs <- tx
  308. }
  309. }
  310. go eth.run()
  311. eth.handshake(t, true)
  312. err := p2p.ExpectMsg(eth, TxMsg, []interface{}{})
  313. if err != nil {
  314. t.Errorf("transactions expected, got %v", err)
  315. }
  316. var delay = 3 * time.Second
  317. tx := &types.Transaction{}
  318. go p2p.Send(eth, TxMsg, []interface{}{tx, tx})
  319. timer := time.After(delay)
  320. for i := int64(0); i < 2; i++ {
  321. select {
  322. case <-txs:
  323. case <-timer:
  324. return
  325. case err := <-eth.quit:
  326. t.Errorf("no error expected, got %v", err)
  327. return
  328. }
  329. }
  330. go p2p.Send(eth, TxMsg, []interface{}{[]interface{}{}})
  331. eth.checkError(ErrDecode, delay)
  332. }
  333. */