| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of go-ethereum. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // gethrpctest is a command to run the external RPC tests. | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"flag" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 16:44:42 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/eth" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/node" | 
					
						
							| 
									
										
										
										
											2016-04-12 16:44:42 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/tests" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/whisper" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const defaultTestKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	testFile = flag.String("json", "", "Path to the .json test file to load") | 
					
						
							|  |  |  | 	testName = flag.String("test", "", "Name of the test from the .json file to run") | 
					
						
							|  |  |  | 	testKey  = flag.String("key", defaultTestKey, "Private key of a test account to inject") | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	flag.Parse() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-27 18:01:30 +02:00
										 |  |  | 	// Enable logging errors, we really do want to see those | 
					
						
							|  |  |  | 	glog.SetV(2) | 
					
						
							|  |  |  | 	glog.SetToStderr(true) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	// Load the test suite to run the RPC against | 
					
						
							|  |  |  | 	tests, err := tests.LoadBlockTests(*testFile) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatalf("Failed to load test suite: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	test, found := tests[*testName] | 
					
						
							|  |  |  | 	if !found { | 
					
						
							|  |  |  | 		log.Fatalf("Requested test (%s) not found within suite", *testName) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	stack, err := MakeSystemNode(*testKey, test) | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatalf("Failed to assemble test stack: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := stack.Start(); err != nil { | 
					
						
							|  |  |  | 		log.Fatalf("Failed to start test node: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer stack.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	log.Println("Test node started...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make sure the tests contained within the suite pass | 
					
						
							|  |  |  | 	if err := RunTest(stack, test); err != nil { | 
					
						
							|  |  |  | 		log.Fatalf("Failed to run the pre-configured test: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	log.Println("Initial test suite passed...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	quit := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 	signal.Notify(quit, os.Interrupt) | 
					
						
							|  |  |  | 	<-quit | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MakeSystemNode configures a protocol stack for the RPC tests based on a given | 
					
						
							|  |  |  | // keystore path and initial pre-state. | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) { | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	// Create a networkless protocol stack | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	stack, err := node.New(&node.Config{ | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 		UseLightweightKDF: true, | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 		IPCPath:           node.DefaultIPCEndpoint(""), | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 		HTTPHost:          node.DefaultHTTPHost, | 
					
						
							|  |  |  | 		HTTPPort:          node.DefaultHTTPPort, | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 		HTTPModules:       []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"}, | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 		WSHost:            node.DefaultWSHost, | 
					
						
							|  |  |  | 		WSPort:            node.DefaultWSPort, | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 		WSModules:         []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"}, | 
					
						
							|  |  |  | 		NoDiscovery:       true, | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Create the keystore and inject an unlocked account if requested | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	accman := stack.AccountManager() | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	if len(privkey) > 0 { | 
					
						
							|  |  |  | 		key, err := crypto.HexToECDSA(privkey) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-02 13:57:15 +01:00
										 |  |  | 		a, err := accman.ImportECDSA(key, "") | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-03 01:09:16 +01:00
										 |  |  | 		if err := accman.Unlock(a, ""); err != nil { | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Initialize and register the Ethereum protocol | 
					
						
							|  |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							| 
									
										
										
										
											2016-03-21 23:00:39 +01:00
										 |  |  | 	if _, err := test.InsertPreState(db); err != nil { | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ethConf := ð.Config{ | 
					
						
							|  |  |  | 		TestGenesisState: db, | 
					
						
							|  |  |  | 		TestGenesisBlock: test.Genesis, | 
					
						
							| 
									
										
										
										
											2016-04-12 16:44:42 +03:00
										 |  |  | 		ChainConfig:      &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock}, | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-11-26 18:35:44 +02:00
										 |  |  | 	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil { | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Initialize and register the Whisper protocol | 
					
						
							| 
									
										
										
										
											2015-11-26 18:35:44 +02:00
										 |  |  | 	if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil { | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return stack, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RunTest executes the specified test against an already pre-configured protocol | 
					
						
							|  |  |  | // stack to ensure basic checks pass before running RPC tests. | 
					
						
							|  |  |  | func RunTest(stack *node.Node, test *tests.BlockTest) error { | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | 	var ethereum *eth.Ethereum | 
					
						
							| 
									
										
										
										
											2015-11-26 18:35:44 +02:00
										 |  |  | 	stack.Service(ðereum) | 
					
						
							| 
									
										
										
										
											2015-11-17 18:33:25 +02:00
										 |  |  | 	blockchain := ethereum.BlockChain() | 
					
						
							| 
									
										
										
										
											2015-11-17 13:39:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Process the blocks and verify the imported headers | 
					
						
							|  |  |  | 	blocks, err := test.TryBlocksInsert(blockchain) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := test.ValidateImportedHeaders(blockchain, blocks); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Retrieve the assembled state and validate it | 
					
						
							|  |  |  | 	stateDb, err := blockchain.State() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := test.ValidatePostState(stateDb); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |