github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/gethrpctest/main.go (about) 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 17 // gethrpctest is a command to run the external RPC tests. 18 package main 19 20 import ( 21 "flag" 22 "fmt" 23 "io/ioutil" 24 "log" 25 "os" 26 "os/signal" 27 28 "path/filepath" 29 30 "github.com/ethereumproject/go-ethereum/accounts" 31 "github.com/ethereumproject/go-ethereum/common" 32 "github.com/ethereumproject/go-ethereum/core" 33 "github.com/ethereumproject/go-ethereum/crypto" 34 "github.com/ethereumproject/go-ethereum/eth" 35 "github.com/ethereumproject/go-ethereum/ethdb" 36 "github.com/ethereumproject/go-ethereum/logger/glog" 37 "github.com/ethereumproject/go-ethereum/node" 38 "github.com/ethereumproject/go-ethereum/tests" 39 "github.com/ethereumproject/go-ethereum/whisper" 40 ) 41 42 // Version is the application revision identifier. It can be set with the linker 43 // as in: go build -ldflags "-X main.Version="`git describe --tags` 44 var Version = "unknown" 45 46 var ( 47 testFile = flag.String("json", "", "Path to the .json test file to load") 48 testName = flag.String("test", "", "Name of the test from the .json file to run") 49 testKey = flag.String("key", defaultTestKey, "Private key of a test account to inject") 50 versionFlag = flag.Bool("version", false, "Prints the revision identifier and exit immediatily.") 51 ) 52 53 const defaultTestKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" 54 55 func main() { 56 flag.Parse() 57 58 if *versionFlag { 59 fmt.Println("gethrpctest version", Version) 60 os.Exit(0) 61 } 62 63 // Enable logging errors, we really do want to see those 64 glog.SetV(2) 65 glog.SetToStderr(true) 66 67 // Load the test suite to run the RPC against 68 tests, err := tests.LoadBlockTests(*testFile) 69 if err != nil { 70 log.Fatalf("Failed to load test suite: %v", err) 71 } 72 test, found := tests[*testName] 73 if !found { 74 log.Fatalf("Requested test (%s) not found within suite", *testName) 75 } 76 // Create the protocol stack to run the test with 77 keydir, err := ioutil.TempDir("", "") 78 if err != nil { 79 log.Fatalf("Failed to create temporary keystore directory: %v", err) 80 } 81 defer os.RemoveAll(keydir) 82 83 stack, err := MakeSystemNode(keydir, *testKey, test) 84 if err != nil { 85 log.Fatalf("Failed to assemble test stack: %v", err) 86 } 87 if err := stack.Start(); err != nil { 88 log.Fatalf("Failed to start test node: %v", err) 89 } 90 defer stack.Stop() 91 92 log.Println("Test node started...") 93 94 // Make sure the tests contained within the suite pass 95 if err := RunTest(stack, test); err != nil { 96 log.Fatalf("Failed to run the pre-configured test: %v", err) 97 } 98 log.Println("Initial test suite passed...") 99 100 quit := make(chan os.Signal, 1) 101 signal.Notify(quit, os.Interrupt) 102 <-quit 103 } 104 105 // MakeSystemNode configures a protocol stack for the RPC tests based on a given 106 // keystore path and initial pre-state. 107 func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node.Node, error) { 108 // Create a networkless protocol stack 109 stack, err := node.New(&node.Config{ 110 IPCPath: node.DefaultIPCEndpoint(filepath.Join(common.DefaultDataDir(), "mainnet")), 111 HTTPHost: common.DefaultHTTPHost, 112 HTTPPort: common.DefaultHTTPPort, 113 HTTPModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"}, 114 WSHost: common.DefaultWSHost, 115 WSPort: common.DefaultWSPort, 116 WSModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"}, 117 NoDiscovery: true, 118 }) 119 if err != nil { 120 return nil, err 121 } 122 // Create the keystore and inject an unlocked account if requested 123 accman, err := accounts.NewManager(keydir, accounts.LightScryptN, accounts.LightScryptP, false) 124 if err != nil { 125 return nil, err 126 } 127 128 if len(privkey) > 0 { 129 key, err := crypto.HexToECDSA(privkey) 130 if err != nil { 131 return nil, err 132 } 133 a, err := accman.ImportECDSA(key, "") 134 if err != nil { 135 return nil, err 136 } 137 if err := accman.Unlock(a, ""); err != nil { 138 return nil, err 139 } 140 } 141 // Initialize and register the Ethereum protocol 142 db, _ := ethdb.NewMemDatabase() 143 if _, err := test.InsertPreState(db); err != nil { 144 return nil, err 145 } 146 ethConf := ð.Config{ 147 TestGenesisState: db, 148 TestGenesisBlock: test.Genesis, 149 ChainConfig: core.DefaultConfigMainnet.ChainConfig, 150 AccountManager: accman, 151 } 152 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil { 153 return nil, err 154 } 155 // Initialize and register the Whisper protocol 156 if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil { 157 return nil, err 158 } 159 return stack, nil 160 } 161 162 // RunTest executes the specified test against an already pre-configured protocol 163 // stack to ensure basic checks pass before running RPC tests. 164 func RunTest(stack *node.Node, test *tests.BlockTest) error { 165 var ethereum *eth.Ethereum 166 stack.Service(ðereum) 167 blockchain := ethereum.BlockChain() 168 169 // Process the blocks and verify the imported headers 170 blocks, err := test.TryBlocksInsert(blockchain) 171 if err != nil { 172 return err 173 } 174 if err := test.ValidateImportedHeaders(blockchain, blocks); err != nil { 175 return err 176 } 177 // Retrieve the assembled state and validate it 178 stateDb, err := blockchain.State() 179 if err != nil { 180 return err 181 } 182 if err := test.ValidatePostState(stateDb); err != nil { 183 return err 184 } 185 return nil 186 }