| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | package tests | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2015-07-07 10:32:05 +02:00
										 |  |  | 	"encoding/hex" | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2015-07-17 23:09:36 +02:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/vm" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							| 
									
										
										
										
											2015-06-11 13:06:56 -04:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func RunStateTestWithReader(ruleSet RuleSet, r io.Reader, skipTests []string) error { | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	tests := make(map[string]VmTest) | 
					
						
							|  |  |  | 	if err := readJson(r, &tests); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2015-06-10 17:04:06 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	if err := runStateTests(ruleSet, tests, skipTests); err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func RunStateTest(ruleSet RuleSet, p string, skipTests []string) error { | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 	tests := make(map[string]VmTest) | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	if err := readJsonFile(p, &tests); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	if err := runStateTests(ruleSet, tests, skipTests); err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func BenchStateTest(ruleSet RuleSet, p string, conf bconf, b *testing.B) error { | 
					
						
							| 
									
										
										
										
											2015-07-17 23:09:36 +02:00
										 |  |  | 	tests := make(map[string]VmTest) | 
					
						
							|  |  |  | 	if err := readJsonFile(p, &tests); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	test, ok := tests[conf.name] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return fmt.Errorf("test not found: %s", conf.name) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX Yeah, yeah... | 
					
						
							|  |  |  | 	env := make(map[string]string) | 
					
						
							|  |  |  | 	env["currentCoinbase"] = test.Env.CurrentCoinbase | 
					
						
							|  |  |  | 	env["currentDifficulty"] = test.Env.CurrentDifficulty | 
					
						
							|  |  |  | 	env["currentGasLimit"] = test.Env.CurrentGasLimit | 
					
						
							|  |  |  | 	env["currentNumber"] = test.Env.CurrentNumber | 
					
						
							|  |  |  | 	env["previousHash"] = test.Env.PreviousHash | 
					
						
							|  |  |  | 	if n, ok := test.Env.CurrentTimestamp.(float64); ok { | 
					
						
							|  |  |  | 		env["currentTimestamp"] = strconv.Itoa(int(n)) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		env["currentTimestamp"] = test.Env.CurrentTimestamp.(string) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 		benchStateTest(ruleSet, test, env, b) | 
					
						
							| 
									
										
										
										
											2015-07-17 23:09:36 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func benchStateTest(ruleSet RuleSet, test VmTest, env map[string]string, b *testing.B) { | 
					
						
							| 
									
										
										
										
											2015-07-17 23:09:36 +02:00
										 |  |  | 	b.StopTimer() | 
					
						
							|  |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	statedb, _ := state.New(common.Hash{}, db) | 
					
						
							| 
									
										
										
										
											2015-07-17 23:09:36 +02:00
										 |  |  | 	for addr, account := range test.Pre { | 
					
						
							|  |  |  | 		obj := StateObjectFromAccount(db, addr, account) | 
					
						
							|  |  |  | 		statedb.SetStateObject(obj) | 
					
						
							|  |  |  | 		for a, v := range account.Storage { | 
					
						
							|  |  |  | 			obj.SetState(common.HexToHash(a), common.HexToHash(v)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	b.StartTimer() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	RunState(ruleSet, statedb, env, test.Exec) | 
					
						
							| 
									
										
										
										
											2015-07-17 23:09:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func runStateTests(ruleSet RuleSet, tests map[string]VmTest, skipTests []string) error { | 
					
						
							| 
									
										
										
										
											2015-06-19 11:38:23 +02:00
										 |  |  | 	skipTest := make(map[string]bool, len(skipTests)) | 
					
						
							|  |  |  | 	for _, name := range skipTests { | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		skipTest[name] = true | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for name, test := range tests { | 
					
						
							| 
									
										
										
										
											2016-01-19 23:48:50 +01:00
										 |  |  | 		if skipTest[name] /*|| name != "callcodecallcode_11" */ { | 
					
						
							| 
									
										
										
										
											2015-06-11 13:06:56 -04:00
										 |  |  | 			glog.Infoln("Skipping state test", name) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2015-06-10 17:04:06 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-19 23:48:50 +01:00
										 |  |  | 		//fmt.Println("StateTest:", name) | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 		if err := runStateTest(ruleSet, test); err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 			return fmt.Errorf("%s: %s\n", name, err.Error()) | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-19 23:48:50 +01:00
										 |  |  | 		//glog.Infoln("State test passed: ", name) | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		//fmt.Println(string(statedb.Dump())) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func runStateTest(ruleSet RuleSet, test VmTest) error { | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	statedb, _ := state.New(common.Hash{}, db) | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	for addr, account := range test.Pre { | 
					
						
							|  |  |  | 		obj := StateObjectFromAccount(db, addr, account) | 
					
						
							|  |  |  | 		statedb.SetStateObject(obj) | 
					
						
							|  |  |  | 		for a, v := range account.Storage { | 
					
						
							|  |  |  | 			obj.SetState(common.HexToHash(a), common.HexToHash(v)) | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	// XXX Yeah, yeah... | 
					
						
							|  |  |  | 	env := make(map[string]string) | 
					
						
							|  |  |  | 	env["currentCoinbase"] = test.Env.CurrentCoinbase | 
					
						
							|  |  |  | 	env["currentDifficulty"] = test.Env.CurrentDifficulty | 
					
						
							|  |  |  | 	env["currentGasLimit"] = test.Env.CurrentGasLimit | 
					
						
							|  |  |  | 	env["currentNumber"] = test.Env.CurrentNumber | 
					
						
							|  |  |  | 	env["previousHash"] = test.Env.PreviousHash | 
					
						
							|  |  |  | 	if n, ok := test.Env.CurrentTimestamp.(float64); ok { | 
					
						
							|  |  |  | 		env["currentTimestamp"] = strconv.Itoa(int(n)) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		env["currentTimestamp"] = test.Env.CurrentTimestamp.(string) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		ret []byte | 
					
						
							|  |  |  | 		// gas  *big.Int | 
					
						
							|  |  |  | 		// err  error | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 		logs vm.Logs | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	ret, logs, _, _ = RunState(ruleSet, statedb, env, test.Transaction) | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-21 11:34:02 +02:00
										 |  |  | 	// Compare expected and actual return | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	rexp := common.FromHex(test.Out) | 
					
						
							|  |  |  | 	if bytes.Compare(rexp, ret) != 0 { | 
					
						
							|  |  |  | 		return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	// check post state | 
					
						
							|  |  |  | 	for addr, account := range test.Post { | 
					
						
							|  |  |  | 		obj := statedb.GetStateObject(common.HexToAddress(addr)) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 		if obj == nil { | 
					
						
							|  |  |  | 			return fmt.Errorf("did not find expected post-state account: %s", addr) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 			return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", obj.Address().Bytes()[:4], common.String2Big(account.Balance), obj.Balance()) | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		if obj.Nonce() != common.String2Big(account.Nonce).Uint64() { | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 			return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", obj.Address().Bytes()[:4], account.Nonce, obj.Nonce()) | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 		for addr, value := range account.Storage { | 
					
						
							| 
									
										
										
										
											2015-06-18 22:38:17 +02:00
										 |  |  | 			v := obj.GetState(common.HexToHash(addr)) | 
					
						
							|  |  |  | 			vexp := common.HexToHash(value) | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-18 22:38:17 +02:00
										 |  |  | 			if v != vexp { | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 				return fmt.Errorf("storage failed:\n%x: %s:\nexpected: %x\nhave:     %x\n(%v %v)\n", obj.Address().Bytes(), addr, vexp, v, vexp.Big(), v.Big()) | 
					
						
							| 
									
										
										
										
											2015-06-10 15:02:16 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 14:14:45 +02:00
										 |  |  | 	root, _ := statedb.Commit() | 
					
						
							|  |  |  | 	if common.HexToHash(test.PostStateRoot) != root { | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 		return fmt.Errorf("Post state root error. Expected: %s have: %x", test.PostStateRoot, root) | 
					
						
							| 
									
										
										
										
											2015-06-10 15:02:16 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-14 17:55:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// check logs | 
					
						
							|  |  |  | 	if len(test.Logs) > 0 { | 
					
						
							|  |  |  | 		if err := checkLogs(test.Logs, logs); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 15:02:16 -04:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func RunState(ruleSet RuleSet, statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) { | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2015-07-07 10:32:05 +02:00
										 |  |  | 		data  = common.FromHex(tx["data"]) | 
					
						
							|  |  |  | 		gas   = common.Big(tx["gasLimit"]) | 
					
						
							|  |  |  | 		price = common.Big(tx["gasPrice"]) | 
					
						
							|  |  |  | 		value = common.Big(tx["value"]) | 
					
						
							|  |  |  | 		nonce = common.Big(tx["nonce"]).Uint64() | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var to *common.Address | 
					
						
							|  |  |  | 	if len(tx["to"]) > 2 { | 
					
						
							|  |  |  | 		t := common.HexToAddress(tx["to"]) | 
					
						
							|  |  |  | 		to = &t | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Set pre compiled contracts | 
					
						
							|  |  |  | 	vm.Precompiled = vm.PrecompiledContracts() | 
					
						
							|  |  |  | 	snapshot := statedb.Copy() | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"])) | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 10:32:05 +02:00
										 |  |  | 	key, _ := hex.DecodeString(tx["secretKey"]) | 
					
						
							|  |  |  | 	addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey) | 
					
						
							|  |  |  | 	message := NewMessage(addr, to, data, value, gas, price, nonce) | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	vmenv := NewEnvFromMap(ruleSet, statedb, env, tx) | 
					
						
							| 
									
										
										
										
											2015-07-07 10:32:05 +02:00
										 |  |  | 	vmenv.origin = addr | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	ret, _, err := core.ApplyMessage(vmenv, message, gaspool) | 
					
						
							|  |  |  | 	if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) { | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 		statedb.Set(snapshot) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-18 14:14:45 +02:00
										 |  |  | 	statedb.Commit() | 
					
						
							| 
									
										
										
										
											2015-06-10 14:38:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ret, vmenv.state.Logs(), vmenv.Gas, err | 
					
						
							|  |  |  | } |