diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go
index 7e09abb11..74203a468 100644
--- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go
+++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go
@@ -172,8 +172,9 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
+ defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
- rval, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState.Copy())
+ rval, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
return rval, err
}
@@ -197,8 +198,9 @@ func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error
func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (*big.Int, error) {
b.mu.Lock()
defer b.mu.Unlock()
+ defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
- _, gas, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState.Copy())
+ _, gas, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
return gas, err
}
diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/key_store_passphrase.go b/vendor/github.com/ethereum/go-ethereum/accounts/key_store_passphrase.go
index 700a4eadc..7758e6f27 100644
--- a/vendor/github.com/ethereum/go-ethereum/accounts/key_store_passphrase.go
+++ b/vendor/github.com/ethereum/go-ethereum/accounts/key_store_passphrase.go
@@ -108,7 +108,8 @@ func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {
return nil, err
}
encryptKey := derivedKey[:16]
- keyBytes := crypto.FromECDSA(key.PrivateKey)
+ keyBytes0 := crypto.FromECDSA(key.PrivateKey)
+ keyBytes := common.LeftPadBytes(keyBytes0, 32)
iv := randentropy.GetEntropyCSPRNG(aes.BlockSize) // 16
cipherText, err := aesCTRXOR(encryptKey, keyBytes, iv)
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/evm/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/evm/main.go
index 3f44e0f3c..22707c1cc 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/evm/main.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/evm/main.go
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog"
"gopkg.in/urfave/cli.v1"
@@ -146,7 +147,9 @@ func run(ctx *cli.Context) error {
)
} else {
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
- receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
+
+ code := common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))
+ receiver.SetCode(crypto.Keccak256Hash(code), code)
ret, err = vmenv.Call(
sender,
receiver.Address(),
@@ -224,22 +227,22 @@ type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true }
-func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
-func (self *VMEnv) Vm() vm.Vm { return self.evm }
-func (self *VMEnv) Db() vm.Database { return self.state }
-func (self *VMEnv) MakeSnapshot() vm.Database { return self.state.Copy() }
-func (self *VMEnv) SetSnapshot(db vm.Database) { self.state.Set(db.(*state.StateDB)) }
-func (self *VMEnv) Origin() common.Address { return *self.transactor }
-func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
-func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
-func (self *VMEnv) Time() *big.Int { return self.time }
-func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
-func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
-func (self *VMEnv) Value() *big.Int { return self.value }
-func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
-func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
-func (self *VMEnv) Depth() int { return 0 }
-func (self *VMEnv) SetDepth(i int) { self.depth = i }
+func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
+func (self *VMEnv) Vm() vm.Vm { return self.evm }
+func (self *VMEnv) Db() vm.Database { return self.state }
+func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() }
+func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) }
+func (self *VMEnv) Origin() common.Address { return *self.transactor }
+func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
+func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
+func (self *VMEnv) Time() *big.Int { return self.time }
+func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
+func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
+func (self *VMEnv) Value() *big.Int { return self.value }
+func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
+func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
+func (self *VMEnv) Depth() int { return 0 }
+func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) common.Hash {
if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 {
return self.block.Hash()
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go
index 293a6ffea..01fce7d1a 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go
@@ -79,7 +79,8 @@ func importChain(ctx *cli.Context) error {
if ctx.GlobalBool(utils.TestNetFlag.Name) {
state.StartingNonce = 1048576 // (2**20)
}
- chain, chainDb := utils.MakeChain(ctx)
+ stack := makeFullNode(ctx)
+ chain, chainDb := utils.MakeChain(ctx, stack)
start := time.Now()
err := utils.ImportChain(chain, ctx.Args().First())
chainDb.Close()
@@ -94,7 +95,8 @@ func exportChain(ctx *cli.Context) error {
if len(ctx.Args()) < 1 {
utils.Fatalf("This command requires an argument.")
}
- chain, _ := utils.MakeChain(ctx)
+ stack := makeFullNode(ctx)
+ chain, _ := utils.MakeChain(ctx, stack)
start := time.Now()
var err error
@@ -122,20 +124,25 @@ func exportChain(ctx *cli.Context) error {
}
func removeDB(ctx *cli.Context) error {
- confirm, err := console.Stdin.PromptConfirm("Remove local database?")
- if err != nil {
- utils.Fatalf("%v", err)
+ stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
+ dbdir := stack.ResolvePath(utils.ChainDbName(ctx))
+ if !common.FileExist(dbdir) {
+ fmt.Println(dbdir, "does not exist")
+ return nil
}
- if confirm {
- fmt.Println("Removing chaindata...")
- start := time.Now()
-
- os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), utils.ChainDbName(ctx)))
-
- fmt.Printf("Removed in %v\n", time.Since(start))
- } else {
+ fmt.Println(dbdir)
+ confirm, err := console.Stdin.PromptConfirm("Remove this database?")
+ switch {
+ case err != nil:
+ utils.Fatalf("%v", err)
+ case !confirm:
fmt.Println("Operation aborted")
+ default:
+ fmt.Println("Removing...")
+ start := time.Now()
+ os.RemoveAll(dbdir)
+ fmt.Printf("Removed in %v\n", time.Since(start))
}
return nil
}
@@ -143,7 +150,8 @@ func removeDB(ctx *cli.Context) error {
func upgradeDB(ctx *cli.Context) error {
glog.Infoln("Upgrading blockchain database")
- chain, chainDb := utils.MakeChain(ctx)
+ stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
+ chain, chainDb := utils.MakeChain(ctx, stack)
bcVersion := core.GetBlockChainVersion(chainDb)
if bcVersion == 0 {
bcVersion = core.BlockChainVersion
@@ -156,10 +164,12 @@ func upgradeDB(ctx *cli.Context) error {
utils.Fatalf("Unable to export chain for reimport %s", err)
}
chainDb.Close()
- os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), utils.ChainDbName(ctx)))
+ if dir := dbDirectory(chainDb); dir != "" {
+ os.RemoveAll(dir)
+ }
// Import the chain file.
- chain, chainDb = utils.MakeChain(ctx)
+ chain, chainDb = utils.MakeChain(ctx, stack)
core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
err := utils.ImportChain(chain, exportFile)
chainDb.Close()
@@ -172,8 +182,17 @@ func upgradeDB(ctx *cli.Context) error {
return nil
}
+func dbDirectory(db ethdb.Database) string {
+ ldb, ok := db.(*ethdb.LDBDatabase)
+ if !ok {
+ return ""
+ }
+ return ldb.Path()
+}
+
func dump(ctx *cli.Context) error {
- chain, chainDb := utils.MakeChain(ctx)
+ stack := makeFullNode(ctx)
+ chain, chainDb := utils.MakeChain(ctx, stack)
for _, arg := range ctx.Args() {
var block *types.Block
if hashish(arg) {
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go
index c3becc844..703ad04db 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go
@@ -114,7 +114,7 @@ func remoteConsole(ctx *cli.Context) error {
})
config := console.Config{
- DataDir: utils.MustMakeDataDir(ctx),
+ DataDir: utils.MakeDataDir(ctx),
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
Client: client,
Preload: utils.MakeConsolePreloads(ctx),
@@ -142,7 +142,7 @@ func remoteConsole(ctx *cli.Context) error {
// for "geth attach" and "geth monitor" with no argument.
func dialRPC(endpoint string) (*rpc.Client, error) {
if endpoint == "" {
- endpoint = node.DefaultIPCEndpoint()
+ endpoint = node.DefaultIPCEndpoint(clientIdentifier)
} else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
// Backwards compatibility with geth < 1.5 which required
// these prefixes.
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go
index f2cbd2414..724a55d27 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go
@@ -36,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
@@ -47,7 +46,7 @@ import (
)
const (
- clientIdentifier = "Geth" // Client identifier to advertise over the network
+ clientIdentifier = "geth" // Client identifier to advertise over the network
)
var (
@@ -251,17 +250,15 @@ func initGenesis(ctx *cli.Context) error {
state.StartingNonce = 1048576 // (2**20)
}
- chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), utils.ChainDbName(ctx)), 0, 0)
- if err != nil {
- utils.Fatalf("could not open database: %v", err)
- }
+ stack := makeFullNode(ctx)
+ chaindb := utils.MakeChainDatabase(ctx, stack)
genesisFile, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("failed to read genesis file: %v", err)
}
- block, err := core.WriteGenesisBlock(chainDb, genesisFile)
+ block, err := core.WriteGenesisBlock(chaindb, genesisFile)
if err != nil {
utils.Fatalf("failed to write genesis block: %v", err)
}
@@ -302,9 +299,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node) {
- // Report geth version
- glog.V(logger.Info).Infof("instance: Geth/%s/%s/%s\n", utils.Version, runtime.Version(), runtime.GOOS)
-
// Start up the node itself
utils.StartNode(stack)
@@ -410,7 +404,7 @@ func gpubench(ctx *cli.Context) error {
}
func version(c *cli.Context) error {
- fmt.Println(clientIdentifier)
+ fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", utils.Version)
if gitCommit != "" {
fmt.Println("Git Commit:", gitCommit)
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/geth/monitorcmd.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/monitorcmd.go
index d1490dce2..b74315dab 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/monitorcmd.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/geth/monitorcmd.go
@@ -35,7 +35,7 @@ import (
var (
monitorCommandAttachFlag = cli.StringFlag{
Name: "attach",
- Value: node.DefaultIPCEndpoint(),
+ Value: node.DefaultIPCEndpoint(clientIdentifier),
Usage: "API endpoint to attach to",
}
monitorCommandRowsFlag = cli.IntFlag{
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/gethrpctest/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/gethrpctest/main.go
index d267dbf58..d0d6e1618 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/gethrpctest/main.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/gethrpctest/main.go
@@ -23,7 +23,6 @@ import (
"os"
"os/signal"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
@@ -88,12 +87,12 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
// Create a networkless protocol stack
stack, err := node.New(&node.Config{
UseLightweightKDF: true,
- IPCPath: node.DefaultIPCEndpoint(),
- HTTPHost: common.DefaultHTTPHost,
- HTTPPort: common.DefaultHTTPPort,
+ IPCPath: node.DefaultIPCEndpoint(""),
+ HTTPHost: node.DefaultHTTPHost,
+ HTTPPort: node.DefaultHTTPPort,
HTTPModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
- WSHost: common.DefaultWSHost,
- WSPort: common.DefaultWSPort,
+ WSHost: node.DefaultWSHost,
+ WSPort: node.DefaultWSPort,
WSModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
NoDiscovery: true,
})
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go b/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go
index 5cbccfe98..11c92d451 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/utils/customflags.go
@@ -137,9 +137,19 @@ func (self *DirectoryFlag) Set(value string) {
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
func expandPath(p string) string {
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
- if user, err := user.Current(); err == nil {
- p = user.HomeDir + p[1:]
+ if home := homeDir(); home != "" {
+ p = home + p[1:]
}
}
return path.Clean(os.ExpandEnv(p))
}
+
+func homeDir() string {
+ if home := os.Getenv("HOME"); home != "" {
+ return home
+ }
+ if usr, err := user.Current(); err == nil {
+ return usr.HomeDir
+ }
+ return ""
+}
diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go b/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go
index 59de43918..5c36236f3 100644
--- a/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go
+++ b/vendor/github.com/ethereum/go-ethereum/cmd/utils/flags.go
@@ -108,7 +108,7 @@ var (
DataDirFlag = DirectoryFlag{
Name: "datadir",
Usage: "Data directory for the databases and keystore",
- Value: DirectoryString{common.DefaultDataDir()},
+ Value: DirectoryString{node.DefaultDataDir()},
}
KeyStoreDirFlag = DirectoryFlag{
Name: "keystore",
@@ -142,7 +142,7 @@ var (
DocRootFlag = DirectoryFlag{
Name: "docroot",
Usage: "Document Root for HTTPClient file scheme",
- Value: DirectoryString{common.HomeDir()},
+ Value: DirectoryString{homeDir()},
}
CacheFlag = cli.IntFlag{
Name: "cache",
@@ -266,12 +266,12 @@ var (
RPCListenAddrFlag = cli.StringFlag{
Name: "rpcaddr",
Usage: "HTTP-RPC server listening interface",
- Value: common.DefaultHTTPHost,
+ Value: node.DefaultHTTPHost,
}
RPCPortFlag = cli.IntFlag{
Name: "rpcport",
Usage: "HTTP-RPC server listening port",
- Value: common.DefaultHTTPPort,
+ Value: node.DefaultHTTPPort,
}
RPCCORSDomainFlag = cli.StringFlag{
Name: "rpccorsdomain",
@@ -289,13 +289,13 @@ var (
}
IPCApiFlag = cli.StringFlag{
Name: "ipcapi",
- Usage: "API's offered over the IPC-RPC interface",
+ Usage: "APIs offered over the IPC-RPC interface",
Value: rpc.DefaultIPCApis,
}
IPCPathFlag = DirectoryFlag{
Name: "ipcpath",
Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
- Value: DirectoryString{common.DefaultIPCSocket},
+ Value: DirectoryString{"geth.ipc"},
}
WSEnabledFlag = cli.BoolFlag{
Name: "ws",
@@ -304,12 +304,12 @@ var (
WSListenAddrFlag = cli.StringFlag{
Name: "wsaddr",
Usage: "WS-RPC server listening interface",
- Value: common.DefaultWSHost,
+ Value: node.DefaultWSHost,
}
WSPortFlag = cli.IntFlag{
Name: "wsport",
Usage: "WS-RPC server listening port",
- Value: common.DefaultWSPort,
+ Value: node.DefaultWSPort,
}
WSApiFlag = cli.StringFlag{
Name: "wsapi",
@@ -428,13 +428,14 @@ func DebugSetup(ctx *cli.Context) error {
return err
}
-// MustMakeDataDir retrieves the currently requested data directory, terminating
+// MakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet,
// the a subdirectory of the specified datadir will be used.
-func MustMakeDataDir(ctx *cli.Context) string {
+func MakeDataDir(ctx *cli.Context) string {
if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
+ // TODO: choose a different location outside of the regular datadir.
if ctx.GlobalBool(TestNetFlag.Name) {
- return filepath.Join(path, "/testnet")
+ return filepath.Join(path, "testnet")
}
return path
}
@@ -479,16 +480,16 @@ func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
return key
}
-// MakeNodeName creates a node name from a base set and the command line flags.
-func MakeNodeName(client, version string, ctx *cli.Context) string {
- name := common.MakeName(client, version)
+// makeNodeUserIdent creates the user identifier from CLI flags.
+func makeNodeUserIdent(ctx *cli.Context) string {
+ var comps []string
if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
- name += "/" + identity
+ comps = append(comps, identity)
}
if ctx.GlobalBool(VMEnableJitFlag.Name) {
- name += "/JIT"
+ comps = append(comps, "JIT")
}
- return name
+ return strings.Join(comps, "/")
}
// MakeBootstrapNodes creates a list of bootstrap nodes from the command line
@@ -644,11 +645,13 @@ func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node {
}
config := &node.Config{
- DataDir: MustMakeDataDir(ctx),
+ DataDir: MakeDataDir(ctx),
KeyStoreDir: ctx.GlobalString(KeyStoreDirFlag.Name),
UseLightweightKDF: ctx.GlobalBool(LightKDFFlag.Name),
PrivateKey: MakeNodeKey(ctx),
- Name: MakeNodeName(name, vsn, ctx),
+ Name: name,
+ Version: vsn,
+ UserIdent: makeNodeUserIdent(ctx),
NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name),
BootstrapNodes: MakeBootstrapNodes(ctx),
ListenAddr: MakeListenAddress(ctx),
@@ -712,7 +715,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
ethConf := ð.Config{
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
- ChainConfig: MustMakeChainConfig(ctx),
+ ChainConfig: MakeChainConfig(ctx, stack),
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
LightMode: ctx.GlobalBool(LightModeFlag.Name),
NoDefSrv: ctx.GlobalBool(NoDefSrvFlag.Name),
@@ -804,16 +807,16 @@ func SetupNetwork(ctx *cli.Context) {
params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name))
}
-// MustMakeChainConfig reads the chain configuration from the database in ctx.Datadir.
-func MustMakeChainConfig(ctx *cli.Context) *core.ChainConfig {
- db := MakeChainDatabase(ctx)
+// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
+func MakeChainConfig(ctx *cli.Context, stack *node.Node) *core.ChainConfig {
+ db := MakeChainDatabase(ctx, stack)
defer db.Close()
- return MustMakeChainConfigFromDb(ctx, db)
+ return MakeChainConfigFromDb(ctx, db)
}
-// MustMakeChainConfigFromDb reads the chain configuration from the given database.
-func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
+// MakeChainConfigFromDb reads the chain configuration from the given database.
+func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
// If the chain is already initialized, use any existing chain configs
config := new(core.ChainConfig)
@@ -864,15 +867,14 @@ func ChainDbName(ctx *cli.Context) string {
}
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
-func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
+func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
var (
- datadir = MustMakeDataDir(ctx)
cache = ctx.GlobalInt(CacheFlag.Name)
handles = MakeDatabaseHandles()
name = ChainDbName(ctx)
)
- chainDb, err := ethdb.NewLDBDatabase(filepath.Join(datadir, name), cache, handles)
+ chainDb, err := stack.OpenDatabase(name, cache, handles)
if err != nil {
Fatalf("Could not open database: %v", err)
}
@@ -880,9 +882,9 @@ func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
}
// MakeChain creates a chain manager from set command line flags.
-func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
+func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
var err error
- chainDb = MakeChainDatabase(ctx)
+ chainDb = MakeChainDatabase(ctx, stack)
if ctx.GlobalBool(OlympicFlag.Name) {
_, err := core.WriteTestNetGenesisBlock(chainDb)
@@ -890,7 +892,7 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
glog.Fatalln(err)
}
}
- chainConfig := MustMakeChainConfigFromDb(ctx, chainDb)
+ chainConfig := MakeChainConfigFromDb(ctx, chainDb)
pow := pow.PoW(core.FakePow{})
if !ctx.GlobalBool(FakePoWFlag.Name) {
diff --git a/vendor/github.com/ethereum/go-ethereum/common/path.go b/vendor/github.com/ethereum/go-ethereum/common/path.go
index cbcd13c4f..bd8da86e7 100644
--- a/vendor/github.com/ethereum/go-ethereum/common/path.go
+++ b/vendor/github.com/ethereum/go-ethereum/common/path.go
@@ -19,10 +19,8 @@ package common
import (
"fmt"
"os"
- "os/user"
"path/filepath"
"runtime"
- "strings"
)
// MakeName creates a node name that follows the ethereum convention
@@ -32,21 +30,6 @@ func MakeName(name, version string) string {
return fmt.Sprintf("%s/v%s/%s/%s", name, version, runtime.GOOS, runtime.Version())
}
-func ExpandHomePath(p string) (path string) {
- path = p
- sep := string(os.PathSeparator)
-
- // Check in case of paths like "/something/~/something/"
- if len(p) > 1 && p[:1+len(sep)] == "~"+sep {
- usr, _ := user.Current()
- dir := usr.HomeDir
-
- path = strings.Replace(p, "~", dir, 1)
- }
-
- return
-}
-
func FileExist(filePath string) bool {
_, err := os.Stat(filePath)
if err != nil && os.IsNotExist(err) {
@@ -62,13 +45,3 @@ func AbsolutePath(Datadir string, filename string) string {
}
return filepath.Join(Datadir, filename)
}
-
-func HomeDir() string {
- if home := os.Getenv("HOME"); home != "" {
- return home
- }
- if usr, err := user.Current(); err == nil {
- return usr.HomeDir
- }
- return ""
-}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go b/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go
index 0b9a5f75d..e3ad9cda0 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go
@@ -131,7 +131,7 @@ func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) {
// TxNonce returns the next valid transaction nonce for the
// account at addr. It panics if the account does not exist.
func (b *BlockGen) TxNonce(addr common.Address) uint64 {
- if !b.statedb.HasAccount(addr) {
+ if !b.statedb.Exist(addr) {
panic("account does not exist")
}
return b.statedb.GetNonce(addr)
diff --git a/vendor/github.com/ethereum/go-ethereum/core/execution.go b/vendor/github.com/ethereum/go-ethereum/core/execution.go
index 82143443c..1cb507ee7 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/execution.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/execution.go
@@ -27,14 +27,14 @@ import (
// Call executes within the given contract
func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
- ret, _, err = exec(env, caller, &addr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
+ ret, _, err = exec(env, caller, &addr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err
}
// CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
callerAddr := caller.Address()
- ret, _, err = exec(env, caller, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
+ ret, _, err = exec(env, caller, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err
}
@@ -43,13 +43,13 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address
callerAddr := caller.Address()
originAddr := env.Origin()
callerValue := caller.Value()
- ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
+ ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
return ret, err
}
// Create creates a new contract with the given code
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
- ret, address, err = exec(env, caller, nil, nil, nil, code, gas, gasPrice, value)
+ ret, address, err = exec(env, caller, nil, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value)
// Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE instruction
@@ -59,7 +59,7 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
return ret, address, err
}
-func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
+func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
@@ -85,7 +85,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
createAccount = true
}
- snapshotPreTransfer := env.MakeSnapshot()
+ snapshotPreTransfer := env.SnapshotDatabase()
var (
from = env.Db().GetAccount(caller.Address())
to vm.Account
@@ -105,7 +105,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
- contract.SetCallCode(codeAddr, code)
+ contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise()
ret, err = evm.Run(contract, input)
@@ -129,13 +129,13 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
if err != nil && (env.RuleSet().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
contract.UseGas(contract.Gas)
- env.SetSnapshot(snapshotPreTransfer)
+ env.RevertToSnapshot(snapshotPreTransfer)
}
return ret, addr, err
}
-func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
+func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
@@ -144,7 +144,7 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
return nil, common.Address{}, vm.DepthError
}
- snapshot := env.MakeSnapshot()
+ snapshot := env.SnapshotDatabase()
var to vm.Account
if !env.Db().Exist(*toAddr) {
@@ -155,14 +155,14 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
// Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
- contract.SetCallCode(codeAddr, code)
+ contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise()
ret, err = evm.Run(contract, input)
if err != nil {
contract.UseGas(contract.Gas)
- env.SetSnapshot(snapshot)
+ env.RevertToSnapshot(snapshot)
}
return ret, addr, err
diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/dump.go b/vendor/github.com/ethereum/go-ethereum/core/state/dump.go
index 58ecd852b..8294d61b9 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/state/dump.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/state/dump.go
@@ -52,7 +52,7 @@ func (self *StateDB) RawDump() Dump {
panic(err)
}
- obj := NewObject(common.BytesToAddress(addr), data, nil)
+ obj := newObject(nil, common.BytesToAddress(addr), data, nil)
account := DumpAccount{
Balance: data.Balance.String(),
Nonce: data.Nonce,
diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/journal.go b/vendor/github.com/ethereum/go-ethereum/core/state/journal.go
new file mode 100644
index 000000000..720c821b9
--- /dev/null
+++ b/vendor/github.com/ethereum/go-ethereum/core/state/journal.go
@@ -0,0 +1,117 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// 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.
+//
+// The go-ethereum library 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package state
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+type journalEntry interface {
+ undo(*StateDB)
+}
+
+type journal []journalEntry
+
+type (
+ // Changes to the account trie.
+ createObjectChange struct {
+ account *common.Address
+ }
+ resetObjectChange struct {
+ prev *StateObject
+ }
+ suicideChange struct {
+ account *common.Address
+ prev bool // whether account had already suicided
+ prevbalance *big.Int
+ }
+
+ // Changes to individual accounts.
+ balanceChange struct {
+ account *common.Address
+ prev *big.Int
+ }
+ nonceChange struct {
+ account *common.Address
+ prev uint64
+ }
+ storageChange struct {
+ account *common.Address
+ key, prevalue common.Hash
+ }
+ codeChange struct {
+ account *common.Address
+ prevcode, prevhash []byte
+ }
+
+ // Changes to other state values.
+ refundChange struct {
+ prev *big.Int
+ }
+ addLogChange struct {
+ txhash common.Hash
+ }
+)
+
+func (ch createObjectChange) undo(s *StateDB) {
+ s.GetStateObject(*ch.account).deleted = true
+ delete(s.stateObjects, *ch.account)
+ delete(s.stateObjectsDirty, *ch.account)
+}
+
+func (ch resetObjectChange) undo(s *StateDB) {
+ s.setStateObject(ch.prev)
+}
+
+func (ch suicideChange) undo(s *StateDB) {
+ obj := s.GetStateObject(*ch.account)
+ if obj != nil {
+ obj.suicided = ch.prev
+ obj.setBalance(ch.prevbalance)
+ }
+}
+
+func (ch balanceChange) undo(s *StateDB) {
+ s.GetStateObject(*ch.account).setBalance(ch.prev)
+}
+
+func (ch nonceChange) undo(s *StateDB) {
+ s.GetStateObject(*ch.account).setNonce(ch.prev)
+}
+
+func (ch codeChange) undo(s *StateDB) {
+ s.GetStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
+}
+
+func (ch storageChange) undo(s *StateDB) {
+ s.GetStateObject(*ch.account).setState(ch.key, ch.prevalue)
+}
+
+func (ch refundChange) undo(s *StateDB) {
+ s.refund = ch.prev
+}
+
+func (ch addLogChange) undo(s *StateDB) {
+ logs := s.logs[ch.txhash]
+ if len(logs) == 1 {
+ delete(s.logs, ch.txhash)
+ } else {
+ s.logs[ch.txhash] = logs[:len(logs)-1]
+ }
+}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go b/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go
index a54620d55..6eab27d9e 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go
@@ -66,6 +66,7 @@ func (self Storage) Copy() Storage {
type StateObject struct {
address common.Address // Ethereum address of this account
data Account
+ db *StateDB
// DB error.
// State objects are used by the consensus core and VM which are
@@ -75,15 +76,17 @@ type StateObject struct {
dbErr error
// Write caches.
- trie *trie.SecureTrie // storage trie, which becomes non-nil on first access
- code Code // contract bytecode, which gets set when code is loaded
- storage Storage // Cached storage (flushed when updated)
+ trie *trie.SecureTrie // storage trie, which becomes non-nil on first access
+ code Code // contract bytecode, which gets set when code is loaded
+
+ cachedStorage Storage // Storage entry cache to avoid duplicate reads
+ dirtyStorage Storage // Storage entries that need to be flushed to disk
// Cache flags.
- // When an object is marked for deletion it will be delete from the trie
- // during the "update" phase of the state transition
+ // When an object is marked suicided it will be delete from the trie
+ // during the "update" phase of the state transition.
dirtyCode bool // true if the code was updated
- remove bool
+ suicided bool
deleted bool
onDirty func(addr common.Address) // Callback method to mark a state object newly dirty
}
@@ -97,15 +100,15 @@ type Account struct {
CodeHash []byte
}
-// NewObject creates a state object.
-func NewObject(address common.Address, data Account, onDirty func(addr common.Address)) *StateObject {
+// newObject creates a state object.
+func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *StateObject {
if data.Balance == nil {
data.Balance = new(big.Int)
}
if data.CodeHash == nil {
data.CodeHash = emptyCodeHash
}
- return &StateObject{address: address, data: data, storage: make(Storage), onDirty: onDirty}
+ return &StateObject{db: db, address: address, data: data, cachedStorage: make(Storage), dirtyStorage: make(Storage), onDirty: onDirty}
}
// EncodeRLP implements rlp.Encoder.
@@ -120,8 +123,8 @@ func (self *StateObject) setError(err error) {
}
}
-func (self *StateObject) MarkForDeletion() {
- self.remove = true
+func (self *StateObject) markSuicided() {
+ self.suicided = true
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
@@ -145,24 +148,38 @@ func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie {
// GetState returns a value in account storage.
func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash {
- value, exists := self.storage[key]
+ value, exists := self.cachedStorage[key]
if exists {
return value
}
// Load from DB in case it is missing.
- tr := self.getTrie(db)
- var ret []byte
- rlp.DecodeBytes(tr.Get(key[:]), &ret)
- value = common.BytesToHash(ret)
+ if enc := self.getTrie(db).Get(key[:]); len(enc) > 0 {
+ _, content, _, err := rlp.Split(enc)
+ if err != nil {
+ self.setError(err)
+ }
+ value.SetBytes(content)
+ }
if (value != common.Hash{}) {
- self.storage[key] = value
+ self.cachedStorage[key] = value
}
return value
}
// SetState updates a value in account storage.
-func (self *StateObject) SetState(key, value common.Hash) {
- self.storage[key] = value
+func (self *StateObject) SetState(db trie.Database, key, value common.Hash) {
+ self.db.journal = append(self.db.journal, storageChange{
+ account: &self.address,
+ key: key,
+ prevalue: self.GetState(db, key),
+ })
+ self.setState(key, value)
+}
+
+func (self *StateObject) setState(key, value common.Hash) {
+ self.cachedStorage[key] = value
+ self.dirtyStorage[key] = value
+
if self.onDirty != nil {
self.onDirty(self.Address())
self.onDirty = nil
@@ -172,7 +189,8 @@ func (self *StateObject) SetState(key, value common.Hash) {
// updateTrie writes cached storage modifications into the object's storage trie.
func (self *StateObject) updateTrie(db trie.Database) {
tr := self.getTrie(db)
- for key, value := range self.storage {
+ for key, value := range self.dirtyStorage {
+ delete(self.dirtyStorage, key)
if (value == common.Hash{}) {
tr.Delete(key[:])
continue
@@ -184,7 +202,7 @@ func (self *StateObject) updateTrie(db trie.Database) {
}
// UpdateRoot sets the trie root to the current root hash of
-func (self *StateObject) UpdateRoot(db trie.Database) {
+func (self *StateObject) updateRoot(db trie.Database) {
self.updateTrie(db)
self.data.Root = self.trie.Hash()
}
@@ -194,7 +212,6 @@ func (self *StateObject) UpdateRoot(db trie.Database) {
func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) error {
self.updateTrie(db)
if self.dbErr != nil {
- fmt.Println("dbErr:", self.dbErr)
return self.dbErr
}
root, err := self.trie.CommitTo(dbw)
@@ -227,6 +244,14 @@ func (c *StateObject) SubBalance(amount *big.Int) {
}
func (self *StateObject) SetBalance(amount *big.Int) {
+ self.db.journal = append(self.db.journal, balanceChange{
+ account: &self.address,
+ prev: new(big.Int).Set(self.data.Balance),
+ })
+ self.setBalance(amount)
+}
+
+func (self *StateObject) setBalance(amount *big.Int) {
self.data.Balance = amount
if self.onDirty != nil {
self.onDirty(self.Address())
@@ -237,12 +262,13 @@ func (self *StateObject) SetBalance(amount *big.Int) {
// Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *StateObject) ReturnGas(gas, price *big.Int) {}
-func (self *StateObject) Copy(db trie.Database, onDirty func(addr common.Address)) *StateObject {
- stateObject := NewObject(self.address, self.data, onDirty)
+func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *StateObject {
+ stateObject := newObject(db, self.address, self.data, onDirty)
stateObject.trie = self.trie
stateObject.code = self.code
- stateObject.storage = self.storage.Copy()
- stateObject.remove = self.remove
+ stateObject.dirtyStorage = self.dirtyStorage.Copy()
+ stateObject.cachedStorage = self.dirtyStorage.Copy()
+ stateObject.suicided = self.suicided
stateObject.dirtyCode = self.dirtyCode
stateObject.deleted = self.deleted
return stateObject
@@ -273,9 +299,19 @@ func (self *StateObject) Code(db trie.Database) []byte {
return code
}
-func (self *StateObject) SetCode(code []byte) {
+func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
+ prevcode := self.Code(self.db.db)
+ self.db.journal = append(self.db.journal, codeChange{
+ account: &self.address,
+ prevhash: self.CodeHash(),
+ prevcode: prevcode,
+ })
+ self.setCode(codeHash, code)
+}
+
+func (self *StateObject) setCode(codeHash common.Hash, code []byte) {
self.code = code
- self.data.CodeHash = crypto.Keccak256(code)
+ self.data.CodeHash = codeHash[:]
self.dirtyCode = true
if self.onDirty != nil {
self.onDirty(self.Address())
@@ -284,6 +320,14 @@ func (self *StateObject) SetCode(code []byte) {
}
func (self *StateObject) SetNonce(nonce uint64) {
+ self.db.journal = append(self.db.journal, nonceChange{
+ account: &self.address,
+ prev: self.data.Nonce,
+ })
+ self.setNonce(nonce)
+}
+
+func (self *StateObject) setNonce(nonce uint64) {
self.data.Nonce = nonce
if self.onDirty != nil {
self.onDirty(self.Address())
@@ -312,15 +356,15 @@ func (self *StateObject) Value() *big.Int {
func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
// When iterating over the storage check the cache first
- for h, value := range self.storage {
+ for h, value := range self.cachedStorage {
cb(h, value)
}
- it := self.trie.Iterator()
+ it := self.getTrie(self.db.db).Iterator()
for it.Next() {
// ignore cached values
key := common.BytesToHash(self.trie.GetKey(it.Key))
- if _, ok := self.storage[key]; !ok {
+ if _, ok := self.cachedStorage[key]; !ok {
cb(key, common.BytesToHash(it.Value))
}
}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go b/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go
index 5c51e3b59..ec9e9392f 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go
@@ -20,10 +20,12 @@ package state
import (
"fmt"
"math/big"
+ "sort"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
@@ -39,12 +41,17 @@ var StartingNonce uint64
const (
// Number of past tries to keep. The arbitrarily chosen value here
// is max uncle depth + 1.
- maxJournalLength = 8
+ maxTrieCacheLength = 8
// Number of codehash->size associations to keep.
codeSizeCacheSize = 100000
)
+type revision struct {
+ id int
+ journalIndex int
+}
+
// StateDBs within the ethereum protocol are used to store anything
// within the merkle trie. StateDBs take care of caching and storing
// nested states. It's the general query interface to retrieve:
@@ -68,6 +75,12 @@ type StateDB struct {
logs map[common.Hash]vm.Logs
logSize uint
+ // Journal of state modifications. This is the backbone of
+ // Snapshot and RevertToSnapshot.
+ journal journal
+ validRevisions []revision
+ nextRevisionId int
+
lock sync.Mutex
}
@@ -123,12 +136,12 @@ func (self *StateDB) Reset(root common.Hash) error {
self.trie = tr
self.stateObjects = make(map[common.Address]*StateObject)
self.stateObjectsDirty = make(map[common.Address]struct{})
- self.refund = new(big.Int)
self.thash = common.Hash{}
self.bhash = common.Hash{}
self.txIndex = 0
self.logs = make(map[common.Hash]vm.Logs)
self.logSize = 0
+ self.clearJournalAndRefund()
return nil
}
@@ -149,7 +162,7 @@ func (self *StateDB) pushTrie(t *trie.SecureTrie) {
self.lock.Lock()
defer self.lock.Unlock()
- if len(self.pastTries) >= maxJournalLength {
+ if len(self.pastTries) >= maxTrieCacheLength {
copy(self.pastTries, self.pastTries[1:])
self.pastTries[len(self.pastTries)-1] = t
} else {
@@ -164,6 +177,8 @@ func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
}
func (self *StateDB) AddLog(log *vm.Log) {
+ self.journal = append(self.journal, addLogChange{txhash: self.thash})
+
log.TxHash = self.thash
log.BlockHash = self.bhash
log.TxIndex = uint(self.txIndex)
@@ -185,13 +200,12 @@ func (self *StateDB) Logs() vm.Logs {
}
func (self *StateDB) AddRefund(gas *big.Int) {
+ self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)})
self.refund.Add(self.refund, gas)
}
-func (self *StateDB) HasAccount(addr common.Address) bool {
- return self.GetStateObject(addr) != nil
-}
-
+// Exist reports whether the given account address exists in the state.
+// Notably this also returns true for suicided accounts.
func (self *StateDB) Exist(addr common.Address) bool {
return self.GetStateObject(addr) != nil
}
@@ -206,7 +220,6 @@ func (self *StateDB) GetBalance(addr common.Address) *big.Int {
if stateObject != nil {
return stateObject.Balance()
}
-
return common.Big0
}
@@ -246,6 +259,14 @@ func (self *StateDB) GetCodeSize(addr common.Address) int {
return size
}
+func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
+ stateObject := self.GetStateObject(addr)
+ if stateObject == nil {
+ return common.Hash{}
+ }
+ return common.BytesToHash(stateObject.CodeHash())
+}
+
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
stateObject := self.GetStateObject(a)
if stateObject != nil {
@@ -254,10 +275,10 @@ func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
return common.Hash{}
}
-func (self *StateDB) IsDeleted(addr common.Address) bool {
+func (self *StateDB) HasSuicided(addr common.Address) bool {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
- return stateObject.remove
+ return stateObject.suicided
}
return false
}
@@ -273,6 +294,13 @@ func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
}
}
+func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) {
+ stateObject := self.GetOrNewStateObject(addr)
+ if stateObject != nil {
+ stateObject.SetBalance(amount)
+ }
+}
+
func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
@@ -283,34 +311,43 @@ func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
func (self *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
- stateObject.SetCode(code)
+ stateObject.SetCode(crypto.Keccak256Hash(code), code)
}
}
func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) {
stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
- stateObject.SetState(key, value)
+ stateObject.SetState(self.db, key, value)
}
}
-func (self *StateDB) Delete(addr common.Address) bool {
+// Suicide marks the given account as suicided.
+// This clears the account balance.
+//
+// The account's state object is still available until the state is committed,
+// GetStateObject will return a non-nil account after Suicide.
+func (self *StateDB) Suicide(addr common.Address) bool {
stateObject := self.GetStateObject(addr)
- if stateObject != nil {
- stateObject.MarkForDeletion()
- stateObject.data.Balance = new(big.Int)
- return true
+ if stateObject == nil {
+ return false
}
-
- return false
+ self.journal = append(self.journal, suicideChange{
+ account: &addr,
+ prev: stateObject.suicided,
+ prevbalance: new(big.Int).Set(stateObject.Balance()),
+ })
+ stateObject.markSuicided()
+ stateObject.data.Balance = new(big.Int)
+ return true
}
//
// Setting, updating & deleting state object methods
//
-// Update the given state object and apply it to state trie
-func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
+// updateStateObject writes the given object to the trie.
+func (self *StateDB) updateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
data, err := rlp.EncodeToBytes(stateObject)
if err != nil {
@@ -319,10 +356,9 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
self.trie.Update(addr[:], data)
}
-// Delete the given state object and delete it from the state trie
-func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
+// deleteStateObject removes the given object from the state trie.
+func (self *StateDB) deleteStateObject(stateObject *StateObject) {
stateObject.deleted = true
-
addr := stateObject.Address()
self.trie.Delete(addr[:])
}
@@ -348,12 +384,12 @@ func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObje
return nil
}
// Insert into the live set.
- obj := NewObject(addr, data, self.MarkStateObjectDirty)
- self.SetStateObject(obj)
+ obj := newObject(self, addr, data, self.MarkStateObjectDirty)
+ self.setStateObject(obj)
return obj
}
-func (self *StateDB) SetStateObject(object *StateObject) {
+func (self *StateDB) setStateObject(object *StateObject) {
self.stateObjects[object.Address()] = object
}
@@ -361,52 +397,55 @@ func (self *StateDB) SetStateObject(object *StateObject) {
func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
stateObject := self.GetStateObject(addr)
if stateObject == nil || stateObject.deleted {
- stateObject = self.CreateStateObject(addr)
+ stateObject, _ = self.createObject(addr)
}
-
return stateObject
}
-// NewStateObject create a state object whether it exist in the trie or not
-func (self *StateDB) newStateObject(addr common.Address) *StateObject {
- if glog.V(logger.Core) {
- glog.Infof("(+) %x\n", addr)
- }
- obj := NewObject(addr, Account{}, self.MarkStateObjectDirty)
- obj.SetNonce(StartingNonce) // sets the object to dirty
- self.stateObjects[addr] = obj
- return obj
-}
-
// MarkStateObjectDirty adds the specified object to the dirty map to avoid costly
// state object cache iteration to find a handful of modified ones.
func (self *StateDB) MarkStateObjectDirty(addr common.Address) {
self.stateObjectsDirty[addr] = struct{}{}
}
-// Creates creates a new state object and takes ownership.
-func (self *StateDB) CreateStateObject(addr common.Address) *StateObject {
- // Get previous (if any)
- so := self.GetStateObject(addr)
- // Create a new one
- newSo := self.newStateObject(addr)
-
- // If it existed set the balance to the new account
- if so != nil {
- newSo.data.Balance = so.data.Balance
+// createObject creates a new state object. If there is an existing account with
+// the given address, it is overwritten and returned as the second return value.
+func (self *StateDB) createObject(addr common.Address) (newobj, prev *StateObject) {
+ prev = self.GetStateObject(addr)
+ newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty)
+ newobj.setNonce(StartingNonce) // sets the object to dirty
+ if prev == nil {
+ if glog.V(logger.Core) {
+ glog.Infof("(+) %x\n", addr)
+ }
+ self.journal = append(self.journal, createObjectChange{account: &addr})
+ } else {
+ self.journal = append(self.journal, resetObjectChange{prev: prev})
}
-
- return newSo
+ self.setStateObject(newobj)
+ return newobj, prev
}
+// CreateAccount explicitly creates a state object. If a state object with the address
+// already exists the balance is carried over to the new account.
+//
+// CreateAccount is called during the EVM CREATE operation. The situation might arise that
+// a contract does the following:
+//
+// 1. sends funds to sha(account ++ (nonce + 1))
+// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
+//
+// Carrying over the balance ensures that Ether doesn't disappear.
func (self *StateDB) CreateAccount(addr common.Address) vm.Account {
- return self.CreateStateObject(addr)
+ new, prev := self.createObject(addr)
+ if prev != nil {
+ new.setBalance(prev.data.Balance)
+ }
+ return new
}
-//
-// Setting, copying of the state methods
-//
-
+// Copy creates a deep, independent copy of the state.
+// Snapshots of the copied state cannot be applied to the copy.
func (self *StateDB) Copy() *StateDB {
self.lock.Lock()
defer self.lock.Unlock()
@@ -425,7 +464,7 @@ func (self *StateDB) Copy() *StateDB {
}
// Copy the dirty states and logs
for addr, _ := range self.stateObjectsDirty {
- state.stateObjects[addr] = self.stateObjects[addr].Copy(self.db, state.MarkStateObjectDirty)
+ state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
state.stateObjectsDirty[addr] = struct{}{}
}
for hash, logs := range self.logs {
@@ -435,21 +474,38 @@ func (self *StateDB) Copy() *StateDB {
return state
}
-func (self *StateDB) Set(state *StateDB) {
- self.lock.Lock()
- defer self.lock.Unlock()
-
- self.db = state.db
- self.trie = state.trie
- self.pastTries = state.pastTries
- self.stateObjects = state.stateObjects
- self.stateObjectsDirty = state.stateObjectsDirty
- self.codeSizeCache = state.codeSizeCache
- self.refund = state.refund
- self.logs = state.logs
- self.logSize = state.logSize
+// Snapshot returns an identifier for the current revision of the state.
+func (self *StateDB) Snapshot() int {
+ id := self.nextRevisionId
+ self.nextRevisionId++
+ self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)})
+ return id
}
+// RevertToSnapshot reverts all state changes made since the given revision.
+func (self *StateDB) RevertToSnapshot(revid int) {
+ // Find the snapshot in the stack of valid snapshots.
+ idx := sort.Search(len(self.validRevisions), func(i int) bool {
+ return self.validRevisions[i].id >= revid
+ })
+ if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid {
+ panic(fmt.Errorf("revision id %v cannot be reverted", revid))
+ }
+ snapshot := self.validRevisions[idx].journalIndex
+
+ // Replay the journal to undo changes.
+ for i := len(self.journal) - 1; i >= snapshot; i-- {
+ self.journal[i].undo(self)
+ }
+ self.journal = self.journal[:snapshot]
+
+ // Remove invalidated snapshots from the stack.
+ self.validRevisions = self.validRevisions[:idx]
+}
+
+// GetRefund returns the current value of the refund counter.
+// The return value must not be modified by the caller and will become
+// invalid at the next call to AddRefund.
func (self *StateDB) GetRefund() *big.Int {
return self.refund
}
@@ -458,16 +514,17 @@ func (self *StateDB) GetRefund() *big.Int {
// It is called in between transactions to get the root hash that
// goes into transaction receipts.
func (s *StateDB) IntermediateRoot() common.Hash {
- s.refund = new(big.Int)
for addr, _ := range s.stateObjectsDirty {
stateObject := s.stateObjects[addr]
- if stateObject.remove {
- s.DeleteStateObject(stateObject)
+ if stateObject.suicided {
+ s.deleteStateObject(stateObject)
} else {
- stateObject.UpdateRoot(s.db)
- s.UpdateStateObject(stateObject)
+ stateObject.updateRoot(s.db)
+ s.updateStateObject(stateObject)
}
}
+ // Invalidate journal because reverting across transactions is not allowed.
+ s.clearJournalAndRefund()
return s.trie.Hash()
}
@@ -477,15 +534,15 @@ func (s *StateDB) IntermediateRoot() common.Hash {
// DeleteSuicides should not be used for consensus related updates
// under any circumstances.
func (s *StateDB) DeleteSuicides() {
- // Reset refund so that any used-gas calculations can use
- // this method.
- s.refund = new(big.Int)
+ // Reset refund so that any used-gas calculations can use this method.
+ s.clearJournalAndRefund()
+
for addr, _ := range s.stateObjectsDirty {
stateObject := s.stateObjects[addr]
// If the object has been removed by a suicide
// flag the object as deleted.
- if stateObject.remove {
+ if stateObject.suicided {
stateObject.deleted = true
}
delete(s.stateObjectsDirty, addr)
@@ -507,15 +564,21 @@ func (s *StateDB) CommitBatch() (root common.Hash, batch ethdb.Batch) {
return root, batch
}
-func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error) {
+func (s *StateDB) clearJournalAndRefund() {
+ s.journal = nil
+ s.validRevisions = s.validRevisions[:0]
s.refund = new(big.Int)
+}
+
+func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error) {
+ defer s.clearJournalAndRefund()
// Commit objects to the trie.
for addr, stateObject := range s.stateObjects {
- if stateObject.remove {
+ if stateObject.suicided {
// If the object has been removed, don't bother syncing it
// and just mark it for deletion in the trie.
- s.DeleteStateObject(stateObject)
+ s.deleteStateObject(stateObject)
} else if _, ok := s.stateObjectsDirty[addr]; ok {
// Write any contract code associated with the state object
if stateObject.code != nil && stateObject.dirtyCode {
@@ -529,7 +592,7 @@ func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error)
return common.Hash{}, err
}
// Update the object in the main account trie.
- s.UpdateStateObject(stateObject)
+ s.updateStateObject(stateObject)
}
delete(s.stateObjectsDirty, addr)
}
@@ -540,7 +603,3 @@ func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error)
}
return root, err
}
-
-func (self *StateDB) Refunds() *big.Int {
- return self.refund
-}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go b/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go
index f8b11a7ce..10a110e0b 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go
@@ -257,7 +257,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
// Make sure the account exist. Non existent accounts
// haven't got funds and well therefor never pass.
- if !currentState.HasAccount(from) {
+ if !currentState.Exist(from) {
return ErrNonExistentAccount
}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/block.go b/vendor/github.com/ethereum/go-ethereum/core/types/block.go
index 9562c8b9b..4accb0ee3 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/types/block.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/types/block.go
@@ -104,7 +104,7 @@ type jsonHeader struct {
Coinbase *common.Address `json:"miner"`
Root *common.Hash `json:"stateRoot"`
TxHash *common.Hash `json:"transactionsRoot"`
- ReceiptHash *common.Hash `json:"receiptRoot"`
+ ReceiptHash *common.Hash `json:"receiptsRoot"`
Bloom *Bloom `json:"logsBloom"`
Difficulty *hexBig `json:"difficulty"`
Number *hexBig `json:"number"`
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go b/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go
index 844d3f328..70455a4c2 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go
@@ -27,7 +27,7 @@ type ContractRef interface {
ReturnGas(*big.Int, *big.Int)
Address() common.Address
Value() *big.Int
- SetCode([]byte)
+ SetCode(common.Hash, []byte)
ForEachStorage(callback func(key, value common.Hash) bool)
}
@@ -44,8 +44,9 @@ type Contract struct {
jumpdests destinations // result of JUMPDEST analysis.
Code []byte
- Input []byte
+ CodeHash common.Hash
CodeAddr *common.Address
+ Input []byte
value, Gas, UsedGas, Price *big.Int
@@ -143,14 +144,16 @@ func (c *Contract) Value() *big.Int {
}
// SetCode sets the code to the contract
-func (self *Contract) SetCode(code []byte) {
+func (self *Contract) SetCode(hash common.Hash, code []byte) {
self.Code = code
+ self.CodeHash = hash
}
// SetCallCode sets the code of the contract and address of the backing data
// object
-func (self *Contract) SetCallCode(addr *common.Address, code []byte) {
+func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
self.Code = code
+ self.CodeHash = hash
self.CodeAddr = addr
}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/environment.go b/vendor/github.com/ethereum/go-ethereum/core/vm/environment.go
index 4bd03de7e..a4b2ac196 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/environment.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/environment.go
@@ -36,9 +36,9 @@ type Environment interface {
// The state database
Db() Database
// Creates a restorable snapshot
- MakeSnapshot() Database
+ SnapshotDatabase() int
// Set database to previous snapshot
- SetSnapshot(Database)
+ RevertToSnapshot(int)
// Address of the original invoker (first occurrence of the VM invoker)
Origin() common.Address
// The block number this VM is invoked on
@@ -94,6 +94,7 @@ type Database interface {
GetNonce(common.Address) uint64
SetNonce(common.Address, uint64)
+ GetCodeHash(common.Address) common.Hash
GetCodeSize(common.Address) int
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
@@ -104,9 +105,12 @@ type Database interface {
GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash)
- Delete(common.Address) bool
+ Suicide(common.Address) bool
+ HasSuicided(common.Address) bool
+
+ // Exist reports whether the given account exists in state.
+ // Notably this should also return true for suicided accounts.
Exist(common.Address) bool
- IsDeleted(common.Address) bool
}
// Account represents a contract or basic ethereum account.
@@ -118,7 +122,7 @@ type Account interface {
Balance() *big.Int
Address() common.Address
ReturnGas(*big.Int, *big.Int)
- SetCode([]byte)
+ SetCode(common.Hash, []byte)
ForEachStorage(cb func(key, value common.Hash) bool)
Value() *big.Int
}
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go b/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go
index 849a8463c..79aee60d2 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go
@@ -614,7 +614,7 @@ func opSuicide(instr instruction, pc *uint64, env Environment, contract *Contrac
balance := env.Db().GetBalance(contract.Address())
env.Db().AddBalance(common.BigToAddress(stack.pop()), balance)
- env.Db().Delete(contract.Address())
+ env.Db().Suicide(contract.Address())
}
// following functions are used by the instruction jump table
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/jit.go b/vendor/github.com/ethereum/go-ethereum/core/vm/jit.go
index 460a68ddd..55d2e0477 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/jit.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/jit.go
@@ -425,7 +425,7 @@ func jitCalculateGasAndSize(env Environment, contract *Contract, instr instructi
}
gas.Set(g)
case SUICIDE:
- if !statedb.IsDeleted(contract.Address()) {
+ if !statedb.HasSuicided(contract.Address()) {
statedb.AddRefund(params.SuicideRefundGas)
}
case MLOAD:
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/env.go b/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/env.go
index a4793c98f..59fbaa792 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/env.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/env.go
@@ -86,11 +86,11 @@ func (self *Env) SetDepth(i int) { self.depth = i }
func (self *Env) CanTransfer(from common.Address, balance *big.Int) bool {
return self.state.GetBalance(from).Cmp(balance) >= 0
}
-func (self *Env) MakeSnapshot() vm.Database {
- return self.state.Copy()
+func (self *Env) SnapshotDatabase() int {
+ return self.state.Snapshot()
}
-func (self *Env) SetSnapshot(copy vm.Database) {
- self.state.Set(copy.(*state.StateDB))
+func (self *Env) RevertToSnapshot(snapshot int) {
+ self.state.RevertToSnapshot(snapshot)
}
func (self *Env) Transfer(from, to vm.Account, amount *big.Int) {
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/runtime.go b/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/runtime.go
index 309d508c3..6d980cb32 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/runtime.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/runtime/runtime.go
@@ -104,7 +104,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
)
// set the receiver's (the executing contract) code for execution.
- receiver.SetCode(code)
+ receiver.SetCode(crypto.Keccak256Hash(code), code)
// Call the code with the given configuration.
ret, err := vmenv.Call(
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/vm.go b/vendor/github.com/ethereum/go-ethereum/core/vm/vm.go
index 9d7b55058..033ada21c 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm/vm.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm/vm.go
@@ -71,10 +71,11 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
return nil, nil
}
- var (
- codehash = crypto.Keccak256Hash(contract.Code) // codehash is used when doing jump dest caching
- program *Program
- )
+ codehash := contract.CodeHash // codehash is used when doing jump dest caching
+ if codehash == (common.Hash{}) {
+ codehash = crypto.Keccak256Hash(contract.Code)
+ }
+ var program *Program
if evm.cfg.EnableJit {
// If the JIT is enabled check the status of the JIT program,
// if it doesn't exist compile a new program in a separate
@@ -302,7 +303,7 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
}
gas.Set(g)
case SUICIDE:
- if !statedb.IsDeleted(contract.Address()) {
+ if !statedb.HasSuicided(contract.Address()) {
statedb.AddRefund(params.SuicideRefundGas)
}
case MLOAD:
diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm_env.go b/vendor/github.com/ethereum/go-ethereum/core/vm_env.go
index e541eaef4..d62eebbd9 100644
--- a/vendor/github.com/ethereum/go-ethereum/core/vm_env.go
+++ b/vendor/github.com/ethereum/go-ethereum/core/vm_env.go
@@ -89,12 +89,12 @@ func (self *VMEnv) CanTransfer(from common.Address, balance *big.Int) bool {
return self.state.GetBalance(from).Cmp(balance) >= 0
}
-func (self *VMEnv) MakeSnapshot() vm.Database {
- return self.state.Copy()
+func (self *VMEnv) SnapshotDatabase() int {
+ return self.state.Snapshot()
}
-func (self *VMEnv) SetSnapshot(copy vm.Database) {
- self.state.Set(copy.(*state.StateDB))
+func (self *VMEnv) RevertToSnapshot(snapshot int) {
+ self.state.RevertToSnapshot(snapshot)
}
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) {
diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go
index 13e7058fa..46d03ed38 100644
--- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go
+++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !amd64 appengine gccgo
+
package sha3
// rc stores the round constants for use in the ι step.
diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go
new file mode 100644
index 000000000..de035c550
--- /dev/null
+++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go
@@ -0,0 +1,13 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!appengine,!gccgo
+
+package sha3
+
+// This function is implemented in keccakf_amd64.s.
+
+//go:noescape
+
+func keccakF1600(state *[25]uint64)
diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s
new file mode 100644
index 000000000..a35335178
--- /dev/null
+++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s
@@ -0,0 +1,392 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!appengine,!gccgo
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources at https://github.com/gvanas/KeccakCodePackage
+
+// Offsets in state
+#define _ba (0*8)
+#define _be (1*8)
+#define _bi (2*8)
+#define _bo (3*8)
+#define _bu (4*8)
+#define _ga (5*8)
+#define _ge (6*8)
+#define _gi (7*8)
+#define _go (8*8)
+#define _gu (9*8)
+#define _ka (10*8)
+#define _ke (11*8)
+#define _ki (12*8)
+#define _ko (13*8)
+#define _ku (14*8)
+#define _ma (15*8)
+#define _me (16*8)
+#define _mi (17*8)
+#define _mo (18*8)
+#define _mu (19*8)
+#define _sa (20*8)
+#define _se (21*8)
+#define _si (22*8)
+#define _so (23*8)
+#define _su (24*8)
+
+// Temporary registers
+#define rT1 AX
+
+// Round vars
+#define rpState DI
+#define rpStack SP
+
+#define rDa BX
+#define rDe CX
+#define rDi DX
+#define rDo R8
+#define rDu R9
+
+#define rBa R10
+#define rBe R11
+#define rBi R12
+#define rBo R13
+#define rBu R14
+
+#define rCa SI
+#define rCe BP
+#define rCi rBi
+#define rCo rBo
+#define rCu R15
+
+#define MOVQ_RBI_RCE MOVQ rBi, rCe
+#define XORQ_RT1_RCA XORQ rT1, rCa
+#define XORQ_RT1_RCE XORQ rT1, rCe
+#define XORQ_RBA_RCU XORQ rBa, rCu
+#define XORQ_RBE_RCU XORQ rBe, rCu
+#define XORQ_RDU_RCU XORQ rDu, rCu
+#define XORQ_RDA_RCA XORQ rDa, rCa
+#define XORQ_RDE_RCE XORQ rDe, rCe
+
+#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \
+ /* Prepare round */ \
+ MOVQ rCe, rDa; \
+ ROLQ $1, rDa; \
+ \
+ MOVQ _bi(iState), rCi; \
+ XORQ _gi(iState), rDi; \
+ XORQ rCu, rDa; \
+ XORQ _ki(iState), rCi; \
+ XORQ _mi(iState), rDi; \
+ XORQ rDi, rCi; \
+ \
+ MOVQ rCi, rDe; \
+ ROLQ $1, rDe; \
+ \
+ MOVQ _bo(iState), rCo; \
+ XORQ _go(iState), rDo; \
+ XORQ rCa, rDe; \
+ XORQ _ko(iState), rCo; \
+ XORQ _mo(iState), rDo; \
+ XORQ rDo, rCo; \
+ \
+ MOVQ rCo, rDi; \
+ ROLQ $1, rDi; \
+ \
+ MOVQ rCu, rDo; \
+ XORQ rCe, rDi; \
+ ROLQ $1, rDo; \
+ \
+ MOVQ rCa, rDu; \
+ XORQ rCi, rDo; \
+ ROLQ $1, rDu; \
+ \
+ /* Result b */ \
+ MOVQ _ba(iState), rBa; \
+ MOVQ _ge(iState), rBe; \
+ XORQ rCo, rDu; \
+ MOVQ _ki(iState), rBi; \
+ MOVQ _mo(iState), rBo; \
+ MOVQ _su(iState), rBu; \
+ XORQ rDe, rBe; \
+ ROLQ $44, rBe; \
+ XORQ rDi, rBi; \
+ XORQ rDa, rBa; \
+ ROLQ $43, rBi; \
+ \
+ MOVQ rBe, rCa; \
+ MOVQ rc, rT1; \
+ ORQ rBi, rCa; \
+ XORQ rBa, rT1; \
+ XORQ rT1, rCa; \
+ MOVQ rCa, _ba(oState); \
+ \
+ XORQ rDu, rBu; \
+ ROLQ $14, rBu; \
+ MOVQ rBa, rCu; \
+ ANDQ rBe, rCu; \
+ XORQ rBu, rCu; \
+ MOVQ rCu, _bu(oState); \
+ \
+ XORQ rDo, rBo; \
+ ROLQ $21, rBo; \
+ MOVQ rBo, rT1; \
+ ANDQ rBu, rT1; \
+ XORQ rBi, rT1; \
+ MOVQ rT1, _bi(oState); \
+ \
+ NOTQ rBi; \
+ ORQ rBa, rBu; \
+ ORQ rBo, rBi; \
+ XORQ rBo, rBu; \
+ XORQ rBe, rBi; \
+ MOVQ rBu, _bo(oState); \
+ MOVQ rBi, _be(oState); \
+ B_RBI_RCE; \
+ \
+ /* Result g */ \
+ MOVQ _gu(iState), rBe; \
+ XORQ rDu, rBe; \
+ MOVQ _ka(iState), rBi; \
+ ROLQ $20, rBe; \
+ XORQ rDa, rBi; \
+ ROLQ $3, rBi; \
+ MOVQ _bo(iState), rBa; \
+ MOVQ rBe, rT1; \
+ ORQ rBi, rT1; \
+ XORQ rDo, rBa; \
+ MOVQ _me(iState), rBo; \
+ MOVQ _si(iState), rBu; \
+ ROLQ $28, rBa; \
+ XORQ rBa, rT1; \
+ MOVQ rT1, _ga(oState); \
+ G_RT1_RCA; \
+ \
+ XORQ rDe, rBo; \
+ ROLQ $45, rBo; \
+ MOVQ rBi, rT1; \
+ ANDQ rBo, rT1; \
+ XORQ rBe, rT1; \
+ MOVQ rT1, _ge(oState); \
+ G_RT1_RCE; \
+ \
+ XORQ rDi, rBu; \
+ ROLQ $61, rBu; \
+ MOVQ rBu, rT1; \
+ ORQ rBa, rT1; \
+ XORQ rBo, rT1; \
+ MOVQ rT1, _go(oState); \
+ \
+ ANDQ rBe, rBa; \
+ XORQ rBu, rBa; \
+ MOVQ rBa, _gu(oState); \
+ NOTQ rBu; \
+ G_RBA_RCU; \
+ \
+ ORQ rBu, rBo; \
+ XORQ rBi, rBo; \
+ MOVQ rBo, _gi(oState); \
+ \
+ /* Result k */ \
+ MOVQ _be(iState), rBa; \
+ MOVQ _gi(iState), rBe; \
+ MOVQ _ko(iState), rBi; \
+ MOVQ _mu(iState), rBo; \
+ MOVQ _sa(iState), rBu; \
+ XORQ rDi, rBe; \
+ ROLQ $6, rBe; \
+ XORQ rDo, rBi; \
+ ROLQ $25, rBi; \
+ MOVQ rBe, rT1; \
+ ORQ rBi, rT1; \
+ XORQ rDe, rBa; \
+ ROLQ $1, rBa; \
+ XORQ rBa, rT1; \
+ MOVQ rT1, _ka(oState); \
+ K_RT1_RCA; \
+ \
+ XORQ rDu, rBo; \
+ ROLQ $8, rBo; \
+ MOVQ rBi, rT1; \
+ ANDQ rBo, rT1; \
+ XORQ rBe, rT1; \
+ MOVQ rT1, _ke(oState); \
+ K_RT1_RCE; \
+ \
+ XORQ rDa, rBu; \
+ ROLQ $18, rBu; \
+ NOTQ rBo; \
+ MOVQ rBo, rT1; \
+ ANDQ rBu, rT1; \
+ XORQ rBi, rT1; \
+ MOVQ rT1, _ki(oState); \
+ \
+ MOVQ rBu, rT1; \
+ ORQ rBa, rT1; \
+ XORQ rBo, rT1; \
+ MOVQ rT1, _ko(oState); \
+ \
+ ANDQ rBe, rBa; \
+ XORQ rBu, rBa; \
+ MOVQ rBa, _ku(oState); \
+ K_RBA_RCU; \
+ \
+ /* Result m */ \
+ MOVQ _ga(iState), rBe; \
+ XORQ rDa, rBe; \
+ MOVQ _ke(iState), rBi; \
+ ROLQ $36, rBe; \
+ XORQ rDe, rBi; \
+ MOVQ _bu(iState), rBa; \
+ ROLQ $10, rBi; \
+ MOVQ rBe, rT1; \
+ MOVQ _mi(iState), rBo; \
+ ANDQ rBi, rT1; \
+ XORQ rDu, rBa; \
+ MOVQ _so(iState), rBu; \
+ ROLQ $27, rBa; \
+ XORQ rBa, rT1; \
+ MOVQ rT1, _ma(oState); \
+ M_RT1_RCA; \
+ \
+ XORQ rDi, rBo; \
+ ROLQ $15, rBo; \
+ MOVQ rBi, rT1; \
+ ORQ rBo, rT1; \
+ XORQ rBe, rT1; \
+ MOVQ rT1, _me(oState); \
+ M_RT1_RCE; \
+ \
+ XORQ rDo, rBu; \
+ ROLQ $56, rBu; \
+ NOTQ rBo; \
+ MOVQ rBo, rT1; \
+ ORQ rBu, rT1; \
+ XORQ rBi, rT1; \
+ MOVQ rT1, _mi(oState); \
+ \
+ ORQ rBa, rBe; \
+ XORQ rBu, rBe; \
+ MOVQ rBe, _mu(oState); \
+ \
+ ANDQ rBa, rBu; \
+ XORQ rBo, rBu; \
+ MOVQ rBu, _mo(oState); \
+ M_RBE_RCU; \
+ \
+ /* Result s */ \
+ MOVQ _bi(iState), rBa; \
+ MOVQ _go(iState), rBe; \
+ MOVQ _ku(iState), rBi; \
+ XORQ rDi, rBa; \
+ MOVQ _ma(iState), rBo; \
+ ROLQ $62, rBa; \
+ XORQ rDo, rBe; \
+ MOVQ _se(iState), rBu; \
+ ROLQ $55, rBe; \
+ \
+ XORQ rDu, rBi; \
+ MOVQ rBa, rDu; \
+ XORQ rDe, rBu; \
+ ROLQ $2, rBu; \
+ ANDQ rBe, rDu; \
+ XORQ rBu, rDu; \
+ MOVQ rDu, _su(oState); \
+ \
+ ROLQ $39, rBi; \
+ S_RDU_RCU; \
+ NOTQ rBe; \
+ XORQ rDa, rBo; \
+ MOVQ rBe, rDa; \
+ ANDQ rBi, rDa; \
+ XORQ rBa, rDa; \
+ MOVQ rDa, _sa(oState); \
+ S_RDA_RCA; \
+ \
+ ROLQ $41, rBo; \
+ MOVQ rBi, rDe; \
+ ORQ rBo, rDe; \
+ XORQ rBe, rDe; \
+ MOVQ rDe, _se(oState); \
+ S_RDE_RCE; \
+ \
+ MOVQ rBo, rDi; \
+ MOVQ rBu, rDo; \
+ ANDQ rBu, rDi; \
+ ORQ rBa, rDo; \
+ XORQ rBi, rDi; \
+ XORQ rBo, rDo; \
+ MOVQ rDi, _si(oState); \
+ MOVQ rDo, _so(oState) \
+
+// func keccakF1600(state *[25]uint64)
+TEXT ·keccakF1600(SB), 0, $200-8
+ MOVQ state+0(FP), rpState
+ SUBQ $(8*25), SP
+
+ // Convert the user state into an internal state
+ NOTQ _be(rpState)
+ NOTQ _bi(rpState)
+ NOTQ _go(rpState)
+ NOTQ _ki(rpState)
+ NOTQ _mi(rpState)
+ NOTQ _sa(rpState)
+
+ // Execute the KeccakF permutation
+ MOVQ _ba(rpState), rCa
+ MOVQ _be(rpState), rCe
+ MOVQ _bu(rpState), rCu
+
+ XORQ _ga(rpState), rCa
+ XORQ _ge(rpState), rCe
+ XORQ _gu(rpState), rCu
+
+ XORQ _ka(rpState), rCa
+ XORQ _ke(rpState), rCe
+ XORQ _ku(rpState), rCu
+
+ XORQ _ma(rpState), rCa
+ XORQ _me(rpState), rCe
+ XORQ _mu(rpState), rCu
+
+ XORQ _sa(rpState), rCa
+ XORQ _se(rpState), rCe
+ MOVQ _si(rpState), rDi
+ MOVQ _so(rpState), rDo
+ XORQ _su(rpState), rCu
+
+ mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP)
+
+ // Revert the internal state to the user state
+ NOTQ _be(rpState)
+ NOTQ _bi(rpState)
+ NOTQ _go(rpState)
+ NOTQ _ki(rpState)
+ NOTQ _mi(rpState)
+ NOTQ _sa(rpState)
+
+ ADDQ $(8*25), SP
+ RET
diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go
index c8fd31cb0..c86167c0b 100644
--- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go
+++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go
@@ -42,7 +42,7 @@ type state struct {
storage [maxRate]byte
// Specific to SHA-3 and SHAKE.
- fixedOutput bool // whether this is a fixed-ouput-length instance
+ fixedOutput bool // whether this is a fixed-output-length instance
outputLen int // the default output size in bytes
state spongeDirection // whether the sponge is absorbing or squeezing
}
diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go
index d622979c1..46a0d63a6 100644
--- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go
+++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!386 appengine
+// +build !amd64,!386,!ppc64le appengine
package sha3
diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go
index c7851a1d8..929a486a7 100644
--- a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go
+++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64 386
+// +build amd64 386 ppc64le
// +build !appengine
package sha3
diff --git a/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go b/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go
index 58dd70d54..639f186c1 100644
--- a/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go
+++ b/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go
@@ -98,12 +98,12 @@ func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int {
}
func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header) (vm.Environment, func() error, error) {
- stateDb := state.(EthApiState).state.Copy()
+ statedb := state.(EthApiState).state
addr, _ := msg.From()
- from := stateDb.GetOrNewStateObject(addr)
+ from := statedb.GetOrNewStateObject(addr)
from.SetBalance(common.MaxBig)
vmError := func() error { return nil }
- return core.NewEnv(stateDb, b.eth.chainConfig, b.eth.blockchain, msg, header, b.eth.chainConfig.VmConfig), vmError, nil
+ return core.NewEnv(statedb, b.eth.chainConfig, b.eth.blockchain, msg, header, b.eth.chainConfig.VmConfig), vmError, nil
}
func (b *EthApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
diff --git a/vendor/github.com/ethereum/go-ethereum/eth/handler.go b/vendor/github.com/ethereum/go-ethereum/eth/handler.go
index cad9075db..f4dd3ade8 100644
--- a/vendor/github.com/ethereum/go-ethereum/eth/handler.go
+++ b/vendor/github.com/ethereum/go-ethereum/eth/handler.go
@@ -17,6 +17,7 @@
package eth
import (
+ "encoding/json"
"errors"
"fmt"
"math"
@@ -375,14 +376,24 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
case query.Origin.Hash != (common.Hash{}) && !query.Reverse:
// Hash based traversal towards the leaf block
- if header := pm.blockchain.GetHeaderByNumber(origin.Number.Uint64() + query.Skip + 1); header != nil {
- if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash {
- query.Origin.Hash = header.Hash()
+ var (
+ current = origin.Number.Uint64()
+ next = current + query.Skip + 1
+ )
+ if next <= current {
+ infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ")
+ glog.V(logger.Warn).Infof("%v: GetBlockHeaders skip overflow attack (current %v, skip %v, next %v)\nMalicious peer infos: %s", p, current, query.Skip, next, infos)
+ unknown = true
+ } else {
+ if header := pm.blockchain.GetHeaderByNumber(next); header != nil {
+ if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash {
+ query.Origin.Hash = header.Hash()
+ } else {
+ unknown = true
+ }
} else {
unknown = true
}
- } else {
- unknown = true
}
case query.Reverse:
// Number based traversal towards the genesis block
diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/database.go b/vendor/github.com/ethereum/go-ethereum/ethdb/database.go
index a0a6efbad..96d9a5982 100644
--- a/vendor/github.com/ethereum/go-ethereum/ethdb/database.go
+++ b/vendor/github.com/ethereum/go-ethereum/ethdb/database.go
@@ -102,6 +102,11 @@ func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) {
}, nil
}
+// Path returns the path to the database directory.
+func (db *LDBDatabase) Path() string {
+ return db.fn
+}
+
// Put puts the given key / value to the queue
func (self *LDBDatabase) Put(key []byte, value []byte) error {
// Measure the database put latency, if requested
diff --git a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go
index 53237f4e4..861e79951 100644
--- a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go
+++ b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go
@@ -614,7 +614,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
"gasUsed": rpc.NewHexNumber(head.GasUsed),
"timestamp": rpc.NewHexNumber(head.Time),
"transactionsRoot": head.TxHash,
- "receiptRoot": head.ReceiptHash,
+ "receiptsRoot": head.ReceiptHash,
}
if inclTx {
@@ -1238,8 +1238,7 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() []*RPCTransaction {
// Resend accepts an existing transaction and a new gas price and limit. It will remove the given transaction from the
// pool and reinsert it with the new gas price and limit.
-func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx *Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) {
-
+func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) {
pending := s.b.GetPoolTransactions()
for _, p := range pending {
if pFrom, err := p.FromFrontier(); err == nil && pFrom == tx.From && p.SigHash() == tx.tx.SigHash() {
@@ -1252,9 +1251,9 @@ func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx *Tx, gasPrice,
var newTx *types.Transaction
if tx.tx.To() == nil {
- newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data())
+ newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasLimit.BigInt(), gasPrice.BigInt(), tx.tx.Data())
} else {
- newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data())
+ newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasLimit.BigInt(), gasPrice.BigInt(), tx.tx.Data())
}
signedTx, err := s.sign(tx.From, newTx)
diff --git a/vendor/github.com/ethereum/go-ethereum/light/state.go b/vendor/github.com/ethereum/go-ethereum/light/state.go
index a2faf0ca3..fc7b36221 100644
--- a/vendor/github.com/ethereum/go-ethereum/light/state.go
+++ b/vendor/github.com/ethereum/go-ethereum/light/state.go
@@ -20,6 +20,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"golang.org/x/net/context"
@@ -156,7 +157,7 @@ func (self *LightState) SetNonce(ctx context.Context, addr common.Address, nonce
func (self *LightState) SetCode(ctx context.Context, addr common.Address, code []byte) error {
stateObject, err := self.GetOrNewStateObject(ctx, addr)
if err == nil && stateObject != nil {
- stateObject.SetCode(code)
+ stateObject.SetCode(crypto.Keccak256Hash(code), code)
}
return err
}
diff --git a/vendor/github.com/ethereum/go-ethereum/light/state_object.go b/vendor/github.com/ethereum/go-ethereum/light/state_object.go
index 9cb677487..61c3888fe 100644
--- a/vendor/github.com/ethereum/go-ethereum/light/state_object.go
+++ b/vendor/github.com/ethereum/go-ethereum/light/state_object.go
@@ -217,9 +217,9 @@ func (self *StateObject) Code() []byte {
}
// SetCode sets the contract code
-func (self *StateObject) SetCode(code []byte) {
+func (self *StateObject) SetCode(hash common.Hash, code []byte) {
self.code = code
- self.codeHash = crypto.Keccak256(code)
+ self.codeHash = hash[:]
self.dirty = true
}
diff --git a/vendor/github.com/ethereum/go-ethereum/light/vm_env.go b/vendor/github.com/ethereum/go-ethereum/light/vm_env.go
index 596143795..d18e97b08 100644
--- a/vendor/github.com/ethereum/go-ethereum/light/vm_env.go
+++ b/vendor/github.com/ethereum/go-ethereum/light/vm_env.go
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
"golang.org/x/net/context"
)
@@ -40,10 +41,7 @@ type VMEnv struct {
msg core.Message
depth int
chain *LightChain
- typ vm.Type
- // structured logging
- logs []vm.StructLog
- err error
+ err error
}
// NewEnv creates a new execution environment based on an ODR capable light state
@@ -53,7 +51,6 @@ func NewEnv(ctx context.Context, state *LightState, chainConfig *core.ChainConfi
chain: chain,
header: header,
msg: msg,
- typ: vm.StdVmTy,
}
env.state = &VMState{ctx: ctx, state: state, env: env}
@@ -69,12 +66,9 @@ func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
func (self *VMEnv) Time() *big.Int { return self.header.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
-func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
-func (self *VMEnv) VmType() vm.Type { return self.typ }
-func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t }
func (self *VMEnv) GetHash(n uint64) common.Hash {
for header := self.chain.GetHeader(self.header.ParentHash, self.header.Number.Uint64()-1); header != nil; header = self.chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
if header.GetNumberU64() == n {
@@ -92,12 +86,12 @@ func (self *VMEnv) CanTransfer(from common.Address, balance *big.Int) bool {
return self.state.GetBalance(from).Cmp(balance) >= 0
}
-func (self *VMEnv) MakeSnapshot() vm.Database {
- return &VMState{ctx: self.ctx, state: self.state.state.Copy(), env: self}
+func (self *VMEnv) SnapshotDatabase() int {
+ return self.state.SnapshotDatabase()
}
-func (self *VMEnv) SetSnapshot(copy vm.Database) {
- self.state.state.Set(copy.(*VMState).state)
+func (self *VMEnv) RevertToSnapshot(idx int) {
+ self.state.RevertToSnapshot(idx)
}
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) {
@@ -111,18 +105,14 @@ func (self *VMEnv) CallCode(me vm.ContractRef, addr common.Address, data []byte,
return core.CallCode(self, me, addr, data, gas, price, value)
}
+func (self *VMEnv) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
+ return core.DelegateCall(self, me, addr, data, gas, price)
+}
+
func (self *VMEnv) Create(me vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
return core.Create(self, me, data, gas, price, value)
}
-func (self *VMEnv) StructLogs() []vm.StructLog {
- return self.logs
-}
-
-func (self *VMEnv) AddStructLog(log vm.StructLog) {
- self.logs = append(self.logs, log)
-}
-
// Error returns the error (if any) that happened during execution.
func (self *VMEnv) Error() error {
return self.err
@@ -132,9 +122,10 @@ func (self *VMEnv) Error() error {
// passes it to any state operation that requires it.
type VMState struct {
vm.Database
- ctx context.Context
- state *LightState
- env *VMEnv
+ ctx context.Context
+ state *LightState
+ snapshots []*LightState
+ env *VMEnv
}
// errHandler handles and stores any state error that happens during execution.
@@ -144,6 +135,16 @@ func (s *VMState) errHandler(err error) {
}
}
+func (self *VMState) SnapshotDatabase() int {
+ self.snapshots = append(self.snapshots, self.state.Copy())
+ return len(self.snapshots) - 1
+}
+
+func (self *VMState) RevertToSnapshot(idx int) {
+ self.state.Set(self.snapshots[idx])
+ self.snapshots = self.snapshots[:idx]
+}
+
// GetAccount returns the account object of the given account or nil if the
// account does not exist
func (s *VMState) GetAccount(addr common.Address) vm.Account {
@@ -203,6 +204,18 @@ func (s *VMState) GetCode(addr common.Address) []byte {
return res
}
+func (s *VMState) GetCodeHash(addr common.Address) common.Hash {
+ res, err := s.state.GetCode(s.ctx, addr)
+ s.errHandler(err)
+ return crypto.Keccak256Hash(res)
+}
+
+func (s *VMState) GetCodeSize(addr common.Address) int {
+ res, err := s.state.GetCode(s.ctx, addr)
+ s.errHandler(err)
+ return len(res)
+}
+
// SetCode sets the contract code at the specified account
func (s *VMState) SetCode(addr common.Address, code []byte) {
err := s.state.SetCode(s.ctx, addr, code)
@@ -234,7 +247,7 @@ func (s *VMState) SetState(addr common.Address, key common.Hash, value common.Ha
}
// Delete marks an account to be removed and clears its balance
-func (s *VMState) Delete(addr common.Address) bool {
+func (s *VMState) Suicide(addr common.Address) bool {
res, err := s.state.Delete(s.ctx, addr)
s.errHandler(err)
return res
@@ -249,7 +262,7 @@ func (s *VMState) Exist(addr common.Address) bool {
// IsDeleted returns true if the given account has been marked for deletion
// or false if the account does not exist
-func (s *VMState) IsDeleted(addr common.Address) bool {
+func (s *VMState) HasSuicided(addr common.Address) bool {
res, err := s.state.IsDeleted(s.ctx, addr)
s.errHandler(err)
return res
diff --git a/vendor/github.com/ethereum/go-ethereum/miner/worker.go b/vendor/github.com/ethereum/go-ethereum/miner/worker.go
index ac1ef5ba3..e5348cef4 100644
--- a/vendor/github.com/ethereum/go-ethereum/miner/worker.go
+++ b/vendor/github.com/ethereum/go-ethereum/miner/worker.go
@@ -171,7 +171,7 @@ func (self *worker) pending() (*types.Block, *state.StateDB) {
self.current.receipts,
), self.current.state
}
- return self.current.Block, self.current.state
+ return self.current.Block, self.current.state.Copy()
}
func (self *worker) start() {
@@ -618,7 +618,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
}
func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, gp *core.GasPool) (error, vm.Logs) {
- snap := env.state.Copy()
+ snap := env.state.Snapshot()
// this is a bit of a hack to force jit for the miners
config := env.config.VmConfig
@@ -629,7 +629,7 @@ func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, g
receipt, logs, _, err := core.ApplyTransaction(env.config, bc, gp, env.state, env.header, tx, env.header.GasUsed, config)
if err != nil {
- env.state.Set(snap)
+ env.state.RevertToSnapshot(snap)
return err, nil
}
env.txs = append(env.txs, tx)
diff --git a/vendor/github.com/ethereum/go-ethereum/node/api.go b/vendor/github.com/ethereum/go-ethereum/node/api.go
index 3523874ab..631e92c8e 100644
--- a/vendor/github.com/ethereum/go-ethereum/node/api.go
+++ b/vendor/github.com/ethereum/go-ethereum/node/api.go
@@ -84,17 +84,17 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *st
}
if host == nil {
- h := common.DefaultHTTPHost
- if api.node.httpHost != "" {
- h = api.node.httpHost
+ h := DefaultHTTPHost
+ if api.node.config.HTTPHost != "" {
+ h = api.node.config.HTTPHost
}
host = &h
}
if port == nil {
- port = rpc.NewHexNumber(api.node.httpPort)
+ port = rpc.NewHexNumber(api.node.config.HTTPPort)
}
if cors == nil {
- cors = &api.node.httpCors
+ cors = &api.node.config.HTTPCors
}
modules := api.node.httpWhitelist
@@ -133,20 +133,20 @@ func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOr
}
if host == nil {
- h := common.DefaultWSHost
- if api.node.wsHost != "" {
- h = api.node.wsHost
+ h := DefaultWSHost
+ if api.node.config.WSHost != "" {
+ h = api.node.config.WSHost
}
host = &h
}
if port == nil {
- port = rpc.NewHexNumber(api.node.wsPort)
+ port = rpc.NewHexNumber(api.node.config.WSPort)
}
if allowedOrigins == nil {
- allowedOrigins = &api.node.wsOrigins
+ allowedOrigins = &api.node.config.WSOrigins
}
- modules := api.node.wsWhitelist
+ modules := api.node.config.WSModules
if apis != nil {
modules = nil
for _, m := range strings.Split(*apis, ",") {
diff --git a/vendor/github.com/ethereum/go-ethereum/node/config.go b/vendor/github.com/ethereum/go-ethereum/node/config.go
index 432da7015..15884a12e 100644
--- a/vendor/github.com/ethereum/go-ethereum/node/config.go
+++ b/vendor/github.com/ethereum/go-ethereum/node/config.go
@@ -18,7 +18,6 @@ package node
import (
"crypto/ecdsa"
- "encoding/json"
"fmt"
"io/ioutil"
"net"
@@ -48,6 +47,18 @@ var (
// P2P network layer of a protocol stack. These values can be further extended by
// all registered services.
type Config struct {
+ // Name sets the instance name of the node. It must not contain the / character and is
+ // used in the devp2p node identifier. The instance name of geth is "geth". If no
+ // value is specified, the basename of the current executable is used.
+ Name string
+
+ // UserIdent, if set, is used as an additional component in the devp2p node identifier.
+ UserIdent string
+
+ // Version should be set to the version number of the program. It is used
+ // in the devp2p node identifier.
+ Version string
+
// DataDir is the file system folder the node should use for any data storage
// requirements. The configured data directory will not be directly shared with
// registered services, instead those can use utility methods to create/access
@@ -80,10 +91,6 @@ type Config struct {
// needed.
PrivateKey *ecdsa.PrivateKey
- // Name sets the node name of this server. Use common.MakeName to create a name
- // that follows existing conventions.
- Name string
-
// NoDiscovery specifies whether the peer discovery mechanism should be started
// or not. Disabling is usually useful for protocol debugging (manual topology).
NoDiscovery bool
@@ -178,9 +185,23 @@ func (c *Config) IPCEndpoint() string {
return c.IPCPath
}
+// NodeDB returns the path to the discovery node database.
+func (c *Config) NodeDB() string {
+ if c.DataDir == "" {
+ return "" // ephemeral
+ }
+ return c.resolvePath("nodes")
+}
+
// DefaultIPCEndpoint returns the IPC path used by default.
-func DefaultIPCEndpoint() string {
- config := &Config{DataDir: common.DefaultDataDir(), IPCPath: common.DefaultIPCSocket}
+func DefaultIPCEndpoint(clientIdentifier string) string {
+ if clientIdentifier == "" {
+ clientIdentifier = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe")
+ if clientIdentifier == "" {
+ panic("empty executable name")
+ }
+ }
+ config := &Config{DataDir: DefaultDataDir(), IPCPath: clientIdentifier + ".ipc"}
return config.IPCEndpoint()
}
@@ -195,7 +216,7 @@ func (c *Config) HTTPEndpoint() string {
// DefaultHTTPEndpoint returns the HTTP endpoint used by default.
func DefaultHTTPEndpoint() string {
- config := &Config{HTTPHost: common.DefaultHTTPHost, HTTPPort: common.DefaultHTTPPort}
+ config := &Config{HTTPHost: DefaultHTTPHost, HTTPPort: DefaultHTTPPort}
return config.HTTPEndpoint()
}
@@ -210,19 +231,80 @@ func (c *Config) WSEndpoint() string {
// DefaultWSEndpoint returns the websocket endpoint used by default.
func DefaultWSEndpoint() string {
- config := &Config{WSHost: common.DefaultWSHost, WSPort: common.DefaultWSPort}
+ config := &Config{WSHost: DefaultWSHost, WSPort: DefaultWSPort}
return config.WSEndpoint()
}
+// NodeName returns the devp2p node identifier.
+func (c *Config) NodeName() string {
+ name := c.name()
+ // Backwards compatibility: previous versions used title-cased "Geth", keep that.
+ if name == "geth" || name == "geth-testnet" {
+ name = "Geth"
+ }
+ if c.UserIdent != "" {
+ name += "/" + c.UserIdent
+ }
+ if c.Version != "" {
+ name += "/v" + c.Version
+ }
+ name += "/" + runtime.GOOS
+ name += "/" + runtime.Version()
+ return name
+}
+
+func (c *Config) name() string {
+ if c.Name == "" {
+ progname := strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe")
+ if progname == "" {
+ panic("empty executable name, set Config.Name")
+ }
+ return progname
+ }
+ return c.Name
+}
+
+// These resources are resolved differently for the "geth" and "geth-testnet" instances.
+var isOldGethResource = map[string]bool{
+ "chaindata": true,
+ "nodes": true,
+ "nodekey": true,
+ "static-nodes.json": true,
+ "trusted-nodes.json": true,
+}
+
+// resolvePath resolves path in the instance directory.
+func (c *Config) resolvePath(path string) string {
+ if filepath.IsAbs(path) {
+ return path
+ }
+ if c.DataDir == "" {
+ return ""
+ }
+ // Backwards-compatibility: ensure that data directory files created
+ // by geth 1.4 are used if they exist.
+ if c.name() == "geth" && isOldGethResource[path] {
+ oldpath := ""
+ if c.Name == "geth" {
+ oldpath = filepath.Join(c.DataDir, path)
+ }
+ if oldpath != "" && common.FileExist(oldpath) {
+ // TODO: print warning
+ return oldpath
+ }
+ }
+ return filepath.Join(c.DataDir, c.name(), path)
+}
+
// NodeKey retrieves the currently configured private key of the node, checking
// first any manually set key, falling back to the one found in the configured
// data folder. If no key can be found, a new one is generated.
func (c *Config) NodeKey() *ecdsa.PrivateKey {
- // Use any specifically configured key
+ // Use any specifically configured key.
if c.PrivateKey != nil {
return c.PrivateKey
}
- // Generate ephemeral key if no datadir is being used
+ // Generate ephemeral key if no datadir is being used.
if c.DataDir == "" {
key, err := crypto.GenerateKey()
if err != nil {
@@ -230,16 +312,22 @@ func (c *Config) NodeKey() *ecdsa.PrivateKey {
}
return key
}
- // Fall back to persistent key from the data directory
- keyfile := filepath.Join(c.DataDir, datadirPrivateKey)
+
+ keyfile := c.resolvePath(datadirPrivateKey)
if key, err := crypto.LoadECDSA(keyfile); err == nil {
return key
}
- // No persistent key found, generate and store a new one
+ // No persistent key found, generate and store a new one.
key, err := crypto.GenerateKey()
if err != nil {
glog.Fatalf("Failed to generate node key: %v", err)
}
+ instanceDir := filepath.Join(c.DataDir, c.name())
+ if err := os.MkdirAll(instanceDir, 0700); err != nil {
+ glog.V(logger.Error).Infof("Failed to persist node key: %v", err)
+ return key
+ }
+ keyfile = filepath.Join(instanceDir, datadirPrivateKey)
if err := crypto.SaveECDSA(keyfile, key); err != nil {
glog.V(logger.Error).Infof("Failed to persist node key: %v", err)
}
@@ -248,12 +336,12 @@ func (c *Config) NodeKey() *ecdsa.PrivateKey {
// StaticNodes returns a list of node enode URLs configured as static nodes.
func (c *Config) StaticNodes() []*discover.Node {
- return c.parsePersistentNodes(datadirStaticNodes)
+ return c.parsePersistentNodes(c.resolvePath(datadirStaticNodes))
}
// TrusterNodes returns a list of node enode URLs configured as trusted nodes.
func (c *Config) TrusterNodes() []*discover.Node {
- return c.parsePersistentNodes(datadirTrustedNodes)
+ return c.parsePersistentNodes(c.resolvePath(datadirTrustedNodes))
}
// parsePersistentNodes parses a list of discovery node URLs loaded from a .json
@@ -267,15 +355,10 @@ func (c *Config) parsePersistentNodes(file string) []*discover.Node {
if _, err := os.Stat(path); err != nil {
return nil
}
- // Load the nodes from the config file
- blob, err := ioutil.ReadFile(path)
- if err != nil {
- glog.V(logger.Error).Infof("Failed to access nodes: %v", err)
- return nil
- }
- nodelist := []string{}
- if err := json.Unmarshal(blob, &nodelist); err != nil {
- glog.V(logger.Error).Infof("Failed to load nodes: %v", err)
+ // Load the nodes from the config file.
+ var nodelist []string
+ if err := common.LoadJSON(path, &nodelist); err != nil {
+ glog.V(logger.Error).Infof("Can't load node file %s: %v", path, err)
return nil
}
// Interpret the list as a discovery node array
diff --git a/vendor/github.com/ethereum/go-ethereum/common/defaults.go b/vendor/github.com/ethereum/go-ethereum/node/defaults.go
similarity index 89%
rename from vendor/github.com/ethereum/go-ethereum/common/defaults.go
rename to vendor/github.com/ethereum/go-ethereum/node/defaults.go
index 8a136fa80..bfe257c8e 100644
--- a/vendor/github.com/ethereum/go-ethereum/common/defaults.go
+++ b/vendor/github.com/ethereum/go-ethereum/node/defaults.go
@@ -14,9 +14,11 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package common
+package node
import (
+ "os"
+ "os/user"
"path/filepath"
"runtime"
)
@@ -33,7 +35,7 @@ const (
// persistence requirements.
func DefaultDataDir() string {
// Try to place the data folder in the user's home dir
- home := HomeDir()
+ home := homeDir()
if home != "" {
if runtime.GOOS == "darwin" {
return filepath.Join(home, "Library", "Ethereum")
@@ -46,3 +48,13 @@ func DefaultDataDir() string {
// As we cannot guess a stable location, return empty and handle later
return ""
}
+
+func homeDir() string {
+ if home := os.Getenv("HOME"); home != "" {
+ return home
+ }
+ if usr, err := user.Current(); err == nil {
+ return usr.HomeDir
+ }
+ return ""
+}
diff --git a/vendor/github.com/ethereum/go-ethereum/node/doc.go b/vendor/github.com/ethereum/go-ethereum/node/doc.go
new file mode 100644
index 000000000..f009e6f85
--- /dev/null
+++ b/vendor/github.com/ethereum/go-ethereum/node/doc.go
@@ -0,0 +1,90 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// 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.
+//
+// The go-ethereum library 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+/*
+Package node sets up multi-protocol Ethereum nodes.
+
+In the model exposed by this package, a node is a collection of services which use shared
+resources to provide RPC APIs. Services can also offer devp2p protocols, which are wired
+up to the devp2p network when the node instance is started.
+
+
+Resources Managed By Node
+
+All file-system resources used by a node instance are located in a directory called the
+data directory. The location of each resource can be overridden through additional node
+configuration. The data directory is optional. If it is not set and the location of a
+resource is otherwise unspecified, package node will create the resource in memory.
+
+To access to the devp2p network, Node configures and starts p2p.Server. Each host on the
+devp2p network has a unique identifier, the node key. The Node instance persists this key
+across restarts. Node also loads static and trusted node lists and ensures that knowledge
+about other hosts is persisted.
+
+JSON-RPC servers which run HTTP, WebSocket or IPC can be started on a Node. RPC modules
+offered by registered services will be offered on those endpoints. Users can restrict any
+endpoint to a subset of RPC modules. Node itself offers the "debug", "admin" and "web3"
+modules.
+
+Service implementations can open LevelDB databases through the service context. Package
+node chooses the file system location of each database. If the node is configured to run
+without a data directory, databases are opened in memory instead.
+
+Node also creates the shared store of encrypted Ethereum account keys. Services can access
+the account manager through the service context.
+
+
+Sharing Data Directory Among Instances
+
+Multiple node instances can share a single data directory if they have distinct instance
+names (set through the Name config option). Sharing behaviour depends on the type of
+resource.
+
+devp2p-related resources (node key, static/trusted node lists, known hosts database) are
+stored in a directory with the same name as the instance. Thus, multiple node instances
+using the same data directory will store this information in different subdirectories of
+the data directory.
+
+LevelDB databases are also stored within the instance subdirectory. If multiple node
+instances use the same data directory, openening the databases with identical names will
+create one database for each instance.
+
+The account key store is shared among all node instances using the same data directory
+unless its location is changed through the KeyStoreDir configuration option.
+
+
+Data Directory Sharing Example
+
+In this exanple, two node instances named A and B are started with the same data
+directory. Mode instance A opens the database "db", node instance B opens the databases
+"db" and "db-2". The following files will be created in the data directory:
+
+ data-directory/
+ A/
+ nodekey -- devp2p node key of instance A
+ nodes/ -- devp2p discovery knowledge database of instance A
+ db/ -- LevelDB content for "db"
+ A.ipc -- JSON-RPC UNIX domain socket endpoint of instance A
+ B/
+ nodekey -- devp2p node key of node B
+ nodes/ -- devp2p discovery knowledge database of instance B
+ static-nodes.json -- devp2p static node list of instance B
+ db/ -- LevelDB content for "db"
+ db-2/ -- LevelDB content for "db-2"
+ B.ipc -- JSON-RPC UNIX domain socket endpoint of instance A
+ keystore/ -- account key store, used by both instances
+*/
+package node
diff --git a/vendor/github.com/ethereum/go-ethereum/node/node.go b/vendor/github.com/ethereum/go-ethereum/node/node.go
index f3be2f763..41c9eb27f 100644
--- a/vendor/github.com/ethereum/go-ethereum/node/node.go
+++ b/vendor/github.com/ethereum/go-ethereum/node/node.go
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-// Package node represents the Ethereum protocol stack container.
package node
import (
@@ -23,16 +22,19 @@ import (
"os"
"path/filepath"
"reflect"
+ "strings"
"sync"
"syscall"
"github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/syndtr/goleveldb/leveldb/storage"
)
var (
@@ -44,14 +46,14 @@ var (
datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
)
-// Node represents a P2P node into which arbitrary (uniquely typed) services might
-// be registered.
+// Node is a container on which services can be registered.
type Node struct {
- datadir string // Path to the currently used data directory
eventmux *event.TypeMux // Event multiplexer used between the services of a stack
+ config *Config
+ accman *accounts.Manager
- accman *accounts.Manager
- ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
+ ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
+ instanceDirLock storage.Storage // prevents concurrent use of instance directory
serverConfig p2p.Config
server *p2p.Server // Currently running P2P networking layer
@@ -66,21 +68,14 @@ type Node struct {
ipcListener net.Listener // IPC RPC listener socket to serve API requests
ipcHandler *rpc.Server // IPC RPC request handler to process the API requests
- httpHost string // HTTP hostname
- httpPort int // HTTP post
httpEndpoint string // HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
httpWhitelist []string // HTTP RPC modules to allow through this endpoint
- httpCors string // HTTP RPC Cross-Origin Resource Sharing header
httpListener net.Listener // HTTP RPC listener socket to server API requests
httpHandler *rpc.Server // HTTP RPC request handler to process the API requests
- wsHost string // Websocket host
- wsPort int // Websocket post
- wsEndpoint string // Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
- wsWhitelist []string // Websocket RPC modules to allow through this endpoint
- wsOrigins string // Websocket RPC allowed origin domains
- wsListener net.Listener // Websocket RPC listener socket to server API requests
- wsHandler *rpc.Server // Websocket RPC request handler to process the API requests
+ wsEndpoint string // Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
+ wsListener net.Listener // Websocket RPC listener socket to server API requests
+ wsHandler *rpc.Server // Websocket RPC request handler to process the API requests
stop chan struct{} // Channel to wait for termination notifications
lock sync.RWMutex
@@ -88,54 +83,45 @@ type Node struct {
// New creates a new P2P node, ready for protocol registration.
func New(conf *Config) (*Node, error) {
- // Ensure the data directory exists, failing if it cannot be created
+ // Copy config and resolve the datadir so future changes to the current
+ // working directory don't affect the node.
+ confCopy := *conf
+ conf = &confCopy
if conf.DataDir != "" {
- if err := os.MkdirAll(conf.DataDir, 0700); err != nil {
+ absdatadir, err := filepath.Abs(conf.DataDir)
+ if err != nil {
return nil, err
}
+ conf.DataDir = absdatadir
}
+ // Ensure that the instance name doesn't cause weird conflicts with
+ // other files in the data directory.
+ if strings.ContainsAny(conf.Name, `/\`) {
+ return nil, errors.New(`Config.Name must not contain '/' or '\'`)
+ }
+ if conf.Name == datadirDefaultKeyStore {
+ return nil, errors.New(`Config.Name cannot be "` + datadirDefaultKeyStore + `"`)
+ }
+ if strings.HasSuffix(conf.Name, ".ipc") {
+ return nil, errors.New(`Config.Name cannot end in ".ipc"`)
+ }
+ // Ensure that the AccountManager method works before the node has started.
+ // We rely on this in cmd/geth.
am, ephemeralKeystore, err := makeAccountManager(conf)
if err != nil {
return nil, err
}
-
- // Assemble the networking layer and the node itself
- nodeDbPath := ""
- if conf.DataDir != "" {
- nodeDbPath = filepath.Join(conf.DataDir, datadirNodeDatabase)
- }
+ // Note: any interaction with Config that would create/touch files
+ // in the data directory or instance directory is delayed until Start.
return &Node{
- datadir: conf.DataDir,
accman: am,
ephemeralKeystore: ephemeralKeystore,
- serverConfig: p2p.Config{
- PrivateKey: conf.NodeKey(),
- Name: conf.Name,
- Discovery: !conf.NoDiscovery,
- BootstrapNodes: conf.BootstrapNodes,
- StaticNodes: conf.StaticNodes(),
- TrustedNodes: conf.TrusterNodes(),
- NodeDatabase: nodeDbPath,
- ListenAddr: conf.ListenAddr,
- NAT: conf.NAT,
- Dialer: conf.Dialer,
- NoDial: conf.NoDial,
- MaxPeers: conf.MaxPeers,
- MaxPendingPeers: conf.MaxPendingPeers,
- },
- serviceFuncs: []ServiceConstructor{},
- ipcEndpoint: conf.IPCEndpoint(),
- httpHost: conf.HTTPHost,
- httpPort: conf.HTTPPort,
- httpEndpoint: conf.HTTPEndpoint(),
- httpWhitelist: conf.HTTPModules,
- httpCors: conf.HTTPCors,
- wsHost: conf.WSHost,
- wsPort: conf.WSPort,
- wsEndpoint: conf.WSEndpoint(),
- wsWhitelist: conf.WSModules,
- wsOrigins: conf.WSOrigins,
- eventmux: new(event.TypeMux),
+ config: conf,
+ serviceFuncs: []ServiceConstructor{},
+ ipcEndpoint: conf.IPCEndpoint(),
+ httpEndpoint: conf.HTTPEndpoint(),
+ wsEndpoint: conf.WSEndpoint(),
+ eventmux: new(event.TypeMux),
}, nil
}
@@ -161,13 +147,36 @@ func (n *Node) Start() error {
if n.server != nil {
return ErrNodeRunning
}
- // Otherwise copy and specialize the P2P configuration
+ if err := n.openDataDir(); err != nil {
+ return err
+ }
+
+ // Initialize the p2p server. This creates the node key and
+ // discovery databases.
+ n.serverConfig = p2p.Config{
+ PrivateKey: n.config.NodeKey(),
+ Name: n.config.NodeName(),
+ Discovery: !n.config.NoDiscovery,
+ BootstrapNodes: n.config.BootstrapNodes,
+ StaticNodes: n.config.StaticNodes(),
+ TrustedNodes: n.config.TrusterNodes(),
+ NodeDatabase: n.config.NodeDB(),
+ ListenAddr: n.config.ListenAddr,
+ NAT: n.config.NAT,
+ Dialer: n.config.Dialer,
+ NoDial: n.config.NoDial,
+ MaxPeers: n.config.MaxPeers,
+ MaxPendingPeers: n.config.MaxPendingPeers,
+ }
running := &p2p.Server{Config: n.serverConfig}
+ glog.V(logger.Info).Infoln("instance:", n.serverConfig.Name)
+
+ // Otherwise copy and specialize the P2P configuration
services := make(map[reflect.Type]Service)
for _, constructor := range n.serviceFuncs {
// Create a new context for the particular service
ctx := &ServiceContext{
- datadir: n.datadir,
+ config: n.config,
services: make(map[reflect.Type]Service),
EventMux: n.eventmux,
AccountManager: n.accman,
@@ -227,6 +236,26 @@ func (n *Node) Start() error {
return nil
}
+func (n *Node) openDataDir() error {
+ if n.config.DataDir == "" {
+ return nil // ephemeral
+ }
+
+ instdir := filepath.Join(n.config.DataDir, n.config.name())
+ if err := os.MkdirAll(instdir, 0700); err != nil {
+ return err
+ }
+ // Try to open the instance directory as LevelDB storage. This creates a lock file
+ // which prevents concurrent use by another instance as well as accidental use of the
+ // instance directory as a database.
+ storage, err := storage.OpenFile(instdir, true)
+ if err != nil {
+ return err
+ }
+ n.instanceDirLock = storage
+ return nil
+}
+
// startRPC is a helper method to start all the various RPC endpoint during node
// startup. It's not meant to be called at any time afterwards as it makes certain
// assumptions about the state of the node.
@@ -244,12 +273,12 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
n.stopInProc()
return err
}
- if err := n.startHTTP(n.httpEndpoint, apis, n.httpWhitelist, n.httpCors); err != nil {
+ if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors); err != nil {
n.stopIPC()
n.stopInProc()
return err
}
- if err := n.startWS(n.wsEndpoint, apis, n.wsWhitelist, n.wsOrigins); err != nil {
+ if err := n.startWS(n.wsEndpoint, apis, n.config.WSModules, n.config.WSOrigins); err != nil {
n.stopHTTP()
n.stopIPC()
n.stopInProc()
@@ -381,7 +410,6 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors
n.httpEndpoint = endpoint
n.httpListener = listener
n.httpHandler = handler
- n.httpCors = cors
return nil
}
@@ -436,7 +464,6 @@ func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrig
n.wsEndpoint = endpoint
n.wsListener = listener
n.wsHandler = handler
- n.wsOrigins = wsOrigins
return nil
}
@@ -465,12 +492,12 @@ func (n *Node) Stop() error {
if n.server == nil {
return ErrNodeStopped
}
- // Otherwise terminate the API, all services and the P2P server too
+
+ // Terminate the API, services and the p2p server.
n.stopWS()
n.stopHTTP()
n.stopIPC()
n.rpcAPIs = nil
-
failure := &StopError{
Services: make(map[reflect.Type]error),
}
@@ -480,9 +507,16 @@ func (n *Node) Stop() error {
}
}
n.server.Stop()
-
n.services = nil
n.server = nil
+
+ // Release instance directory lock.
+ if n.instanceDirLock != nil {
+ n.instanceDirLock.Close()
+ n.instanceDirLock = nil
+ }
+
+ // unblock n.Wait
close(n.stop)
// Remove the keystore if it was created ephemerally.
@@ -566,7 +600,7 @@ func (n *Node) Service(service interface{}) error {
// DataDir retrieves the current datadir used by the protocol stack.
func (n *Node) DataDir() string {
- return n.datadir
+ return n.config.DataDir
}
// AccountManager retrieves the account manager used by the protocol stack.
@@ -595,6 +629,21 @@ func (n *Node) EventMux() *event.TypeMux {
return n.eventmux
}
+// OpenDatabase opens an existing database with the given name (or creates one if no
+// previous can be found) from within the node's instance directory. If the node is
+// ephemeral, a memory database is returned.
+func (n *Node) OpenDatabase(name string, cache, handles int) (ethdb.Database, error) {
+ if n.config.DataDir == "" {
+ return ethdb.NewMemDatabase()
+ }
+ return ethdb.NewLDBDatabase(n.config.resolvePath(name), cache, handles)
+}
+
+// ResolvePath returns the absolute path of a resource in the instance directory.
+func (n *Node) ResolvePath(x string) string {
+ return n.config.resolvePath(x)
+}
+
// apis returns the collection of RPC descriptors this node offers.
func (n *Node) apis() []rpc.API {
return []rpc.API{
diff --git a/vendor/github.com/ethereum/go-ethereum/node/service.go b/vendor/github.com/ethereum/go-ethereum/node/service.go
index 51531466b..1cd1fe808 100644
--- a/vendor/github.com/ethereum/go-ethereum/node/service.go
+++ b/vendor/github.com/ethereum/go-ethereum/node/service.go
@@ -17,7 +17,6 @@
package node
import (
- "path/filepath"
"reflect"
"github.com/ethereum/go-ethereum/accounts"
@@ -31,7 +30,7 @@ import (
// the protocol stack, that is passed to all constructors to be optionally used;
// as well as utility methods to operate on the service environment.
type ServiceContext struct {
- datadir string // Data directory for protocol persistence
+ config *Config
services map[reflect.Type]Service // Index of the already constructed services
EventMux *event.TypeMux // Event multiplexer used for decoupled notifications
AccountManager *accounts.Manager // Account manager created by the node.
@@ -41,10 +40,10 @@ type ServiceContext struct {
// if no previous can be found) from within the node's data directory. If the
// node is an ephemeral one, a memory database is returned.
func (ctx *ServiceContext) OpenDatabase(name string, cache int, handles int) (ethdb.Database, error) {
- if ctx.datadir == "" {
+ if ctx.config.DataDir == "" {
return ethdb.NewMemDatabase()
}
- return ethdb.NewLDBDatabase(filepath.Join(ctx.datadir, name), cache, handles)
+ return ethdb.NewLDBDatabase(ctx.config.resolvePath(name), cache, handles)
}
// Service retrieves a currently running service registered of a specific type.
@@ -64,11 +63,13 @@ type ServiceConstructor func(ctx *ServiceContext) (Service, error)
// Service is an individual protocol that can be registered into a node.
//
// Notes:
-// - Service life-cycle management is delegated to the node. The service is
-// allowed to initialize itself upon creation, but no goroutines should be
-// spun up outside of the Start method.
-// - Restart logic is not required as the node will create a fresh instance
-// every time a service is started.
+//
+// • Service life-cycle management is delegated to the node. The service is allowed to
+// initialize itself upon creation, but no goroutines should be spun up outside of the
+// Start method.
+//
+// • Restart logic is not required as the node will create a fresh instance
+// every time a service is started.
type Service interface {
// Protocols retrieves the P2P protocols the service wishes to start.
Protocols() []p2p.Protocol
diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/nat/nat.go b/vendor/github.com/ethereum/go-ethereum/p2p/nat/nat.go
index 377dc406b..f9ba93613 100644
--- a/vendor/github.com/ethereum/go-ethereum/p2p/nat/nat.go
+++ b/vendor/github.com/ethereum/go-ethereum/p2p/nat/nat.go
@@ -197,11 +197,7 @@ type autodisc struct {
func startautodisc(what string, doit func() Interface) Interface {
// TODO: monitor network configuration and rerun doit when it changes.
- ad := &autodisc{what: what, doit: doit}
- // Start the auto discovery as early as possible so it is already
- // in progress when the rest of the stack calls the methods.
- go ad.wait()
- return ad
+ return &autodisc{what: what, doit: doit}
}
func (n *autodisc) AddMapping(protocol string, extport, intport int, name string, lifetime time.Duration) error {
diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/http.go b/vendor/github.com/ethereum/go-ethereum/rpc/http.go
index afcdd4bd6..c923580bf 100644
--- a/vendor/github.com/ethereum/go-ethereum/rpc/http.go
+++ b/vendor/github.com/ethereum/go-ethereum/rpc/http.go
@@ -170,6 +170,7 @@ func newCorsHandler(srv *Server, corsString string) http.Handler {
c := cors.New(cors.Options{
AllowedOrigins: allowedOrigins,
AllowedMethods: []string{"POST", "GET"},
+ MaxAge: 600,
})
return c.Handler(srv)
}
diff --git a/vendor/github.com/ethereum/go-ethereum/trie/trie.go b/vendor/github.com/ethereum/go-ethereum/trie/trie.go
index 93e189e2e..55598af98 100644
--- a/vendor/github.com/ethereum/go-ethereum/trie/trie.go
+++ b/vendor/github.com/ethereum/go-ethereum/trie/trie.go
@@ -22,7 +22,7 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
@@ -30,11 +30,14 @@ import (
var (
// This is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
-
// This is the known hash of an empty state trie entry.
- emptyState = crypto.Keccak256Hash(nil)
+ emptyState common.Hash
)
+func init() {
+ sha3.NewKeccak256().Sum(emptyState[:0])
+}
+
// Database must be implemented by backing stores for the trie.
type Database interface {
DatabaseWriter
@@ -374,6 +377,9 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
// n still contains at least two values and cannot be reduced.
return true, n, nil
+ case valueNode:
+ return true, nil, nil
+
case nil:
return false, nil, nil