main.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU 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. // go-ethereum 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 General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. // gethrpctest is a command to run the external RPC tests.
  17. package main
  18. import (
  19. "flag"
  20. "io/ioutil"
  21. "log"
  22. "os"
  23. "os/signal"
  24. "github.com/ethereum/go-ethereum/accounts"
  25. "github.com/ethereum/go-ethereum/common"
  26. "github.com/ethereum/go-ethereum/core"
  27. "github.com/ethereum/go-ethereum/crypto"
  28. "github.com/ethereum/go-ethereum/eth"
  29. "github.com/ethereum/go-ethereum/ethdb"
  30. "github.com/ethereum/go-ethereum/logger/glog"
  31. "github.com/ethereum/go-ethereum/node"
  32. "github.com/ethereum/go-ethereum/params"
  33. "github.com/ethereum/go-ethereum/tests"
  34. "github.com/ethereum/go-ethereum/whisper"
  35. )
  36. const defaultTestKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
  37. var (
  38. testFile = flag.String("json", "", "Path to the .json test file to load")
  39. testName = flag.String("test", "", "Name of the test from the .json file to run")
  40. testKey = flag.String("key", defaultTestKey, "Private key of a test account to inject")
  41. )
  42. func main() {
  43. flag.Parse()
  44. // Enable logging errors, we really do want to see those
  45. glog.SetV(2)
  46. glog.SetToStderr(true)
  47. // Load the test suite to run the RPC against
  48. tests, err := tests.LoadBlockTests(*testFile)
  49. if err != nil {
  50. log.Fatalf("Failed to load test suite: %v", err)
  51. }
  52. test, found := tests[*testName]
  53. if !found {
  54. log.Fatalf("Requested test (%s) not found within suite", *testName)
  55. }
  56. // Create the protocol stack to run the test with
  57. keydir, err := ioutil.TempDir("", "")
  58. if err != nil {
  59. log.Fatalf("Failed to create temporary keystore directory: %v", err)
  60. }
  61. defer os.RemoveAll(keydir)
  62. stack, err := MakeSystemNode(keydir, *testKey, test)
  63. if err != nil {
  64. log.Fatalf("Failed to assemble test stack: %v", err)
  65. }
  66. if err := stack.Start(); err != nil {
  67. log.Fatalf("Failed to start test node: %v", err)
  68. }
  69. defer stack.Stop()
  70. log.Println("Test node started...")
  71. // Make sure the tests contained within the suite pass
  72. if err := RunTest(stack, test); err != nil {
  73. log.Fatalf("Failed to run the pre-configured test: %v", err)
  74. }
  75. log.Println("Initial test suite passed...")
  76. quit := make(chan os.Signal, 1)
  77. signal.Notify(quit, os.Interrupt)
  78. <-quit
  79. }
  80. // MakeSystemNode configures a protocol stack for the RPC tests based on a given
  81. // keystore path and initial pre-state.
  82. func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node.Node, error) {
  83. // Create a networkless protocol stack
  84. stack, err := node.New(&node.Config{
  85. IPCPath: node.DefaultIPCEndpoint(),
  86. HTTPHost: common.DefaultHTTPHost,
  87. HTTPPort: common.DefaultHTTPPort,
  88. HTTPModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
  89. WSHost: common.DefaultWSHost,
  90. WSPort: common.DefaultWSPort,
  91. WSModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
  92. NoDiscovery: true,
  93. })
  94. if err != nil {
  95. return nil, err
  96. }
  97. // Create the keystore and inject an unlocked account if requested
  98. accman := accounts.NewPlaintextManager(keydir)
  99. if len(privkey) > 0 {
  100. key, err := crypto.HexToECDSA(privkey)
  101. if err != nil {
  102. return nil, err
  103. }
  104. a, err := accman.ImportECDSA(key, "")
  105. if err != nil {
  106. return nil, err
  107. }
  108. if err := accman.Unlock(a, ""); err != nil {
  109. return nil, err
  110. }
  111. }
  112. // Initialize and register the Ethereum protocol
  113. db, _ := ethdb.NewMemDatabase()
  114. if _, err := test.InsertPreState(db); err != nil {
  115. return nil, err
  116. }
  117. ethConf := &eth.Config{
  118. TestGenesisState: db,
  119. TestGenesisBlock: test.Genesis,
  120. ChainConfig: &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
  121. AccountManager: accman,
  122. }
  123. if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
  124. return nil, err
  125. }
  126. // Initialize and register the Whisper protocol
  127. if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil {
  128. return nil, err
  129. }
  130. return stack, nil
  131. }
  132. // RunTest executes the specified test against an already pre-configured protocol
  133. // stack to ensure basic checks pass before running RPC tests.
  134. func RunTest(stack *node.Node, test *tests.BlockTest) error {
  135. var ethereum *eth.Ethereum
  136. stack.Service(&ethereum)
  137. blockchain := ethereum.BlockChain()
  138. // Process the blocks and verify the imported headers
  139. blocks, err := test.TryBlocksInsert(blockchain)
  140. if err != nil {
  141. return err
  142. }
  143. if err := test.ValidateImportedHeaders(blockchain, blocks); err != nil {
  144. return err
  145. }
  146. // Retrieve the assembled state and validate it
  147. stateDb, err := blockchain.State()
  148. if err != nil {
  149. return err
  150. }
  151. if err := test.ValidatePostState(stateDb); err != nil {
  152. return err
  153. }
  154. return nil
  155. }