diff --git a/cmd/geth/main.go b/cmd/geth/main.go index fa9beafd05..2c4cb5ae1e 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -314,6 +314,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.ExecFlag, utils.WhisperEnabledFlag, utils.DevModeFlag, + utils.TestNetFlag, utils.VMDebugFlag, utils.VMForceJitFlag, utils.VMJitCacheFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index dea43bc5cf..67f8f0c57c 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -125,6 +125,10 @@ var ( Name: "dev", Usage: "Developer mode. This mode creates a private network and sets several debugging flags", } + TestNetFlag = cli.BoolFlag{ + Name: "testnet", + Usage: "Testnet mode. This enables your node to operate on the testnet", + } IdentityFlag = cli.StringFlag{ Name: "identity", Usage: "Custom node name", @@ -452,6 +456,17 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name), } + if ctx.GlobalBool(DevModeFlag.Name) && ctx.GlobalBool(TestNetFlag.Name) { + glog.Fatalf("%s and %s are mutually exclusive\n", DevModeFlag.Name, TestNetFlag.Name) + } + + if ctx.GlobalBool(TestNetFlag.Name) { + // testnet is always stored in the testnet folder + cfg.DataDir += "/testnet" + cfg.NetworkId = 2 + cfg.TestNet = true + } + if ctx.GlobalBool(DevModeFlag.Name) { if !ctx.GlobalIsSet(VMDebugFlag.Name) { cfg.VmDebug = true @@ -540,6 +555,9 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database // MakeChain creates an account manager from set command line flags. func MakeAccountManager(ctx *cli.Context) *accounts.Manager { dataDir := MustDataDir(ctx) + if ctx.GlobalBool(TestNetFlag.Name) { + dataDir += "/testnet" + } ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore")) return accounts.NewManager(ks) } diff --git a/core/genesis.go b/core/genesis.go index bf97da2e24..bfa8696afc 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -155,6 +155,27 @@ func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) } func WriteTestNetGenesisBlock(chainDb ethdb.Database, nonce uint64) (*types.Block, error) { + testGenesis := fmt.Sprintf(`{ + "nonce": "0x%x", + "difficulty": "0x20000", + "mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578", + "coinbase": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2FEFD8", + "alloc": { + "0000000000000000000000000000000000000001": { "balance": "1" }, + "0000000000000000000000000000000000000002": { "balance": "1" }, + "0000000000000000000000000000000000000003": { "balance": "1" }, + "0000000000000000000000000000000000000004": { "balance": "1" }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } + } +}`, types.EncodeNonce(nonce)) + return WriteGenesisBlock(chainDb, strings.NewReader(testGenesis)) +} + +func WriteOlympicGenesisBlock(chainDb ethdb.Database, nonce uint64) (*types.Block, error) { testGenesis := fmt.Sprintf(`{ "nonce":"0x%x", "gasLimit":"0x%x", diff --git a/core/state/statedb.go b/core/state/statedb.go index 499ea5f524..ad673aecba 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -28,6 +28,10 @@ import ( "github.com/ethereum/go-ethereum/trie" ) +// The starting nonce determines the default nonce when new accounts are being +// created. +var StartingNonce uint64 + // 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: @@ -263,6 +267,7 @@ func (self *StateDB) newStateObject(addr common.Address) *StateObject { } stateObject := NewStateObject(addr, self.db) + stateObject.SetNonce(StartingNonce) self.stateObjects[addr.Str()] = stateObject return stateObject diff --git a/eth/backend.go b/eth/backend.go index a480b49310..83eefca5b5 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/core" + "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" @@ -69,12 +70,17 @@ var ( discover.MustParseNode("enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303"), } + defaultTestNetBootNodes = []*discover.Node{ + discover.MustParseNode("enode://5374c1bff8df923d3706357eeb4983cd29a63be40a269aaa2296ee5f3b2119a8978c0ed68b8f6fc84aad0df18790417daadf91a4bfbb786a16c9b0a199fa254a@92.51.165.126:30303"), + } + staticNodes = "static-nodes.json" // Path within to search for the static node list trustedNodes = "trusted-nodes.json" // Path within to search for the trusted node list ) type Config struct { DevMode bool + TestNet bool Name string NetworkId int @@ -133,6 +139,10 @@ type Config struct { func (cfg *Config) parseBootNodes() []*discover.Node { if cfg.BootNodes == "" { + if cfg.TestNet { + return defaultTestNetBootNodes + } + return defaultBootNodes } var ns []*discover.Node @@ -309,7 +319,13 @@ func New(config *Config) (*Ethereum, error) { glog.V(logger.Error).Infoln("Starting Olympic network") fallthrough case config.DevMode: - _, err := core.WriteTestNetGenesisBlock(chainDb, 42) + _, err := core.WriteOlympicGenesisBlock(chainDb, 42) + if err != nil { + return nil, err + } + case config.TestNet: + state.StartingNonce = 1048576 // (2**20) + _, err := core.WriteTestNetGenesisBlock(chainDb, 0x6d6f7264656e) if err != nil { return nil, err }