Merge remote-tracking branch 'origin' into rpcargs

Conflicts:
	rpc/args.go
This commit is contained in:
Taylor Gerring 2015-03-26 22:42:46 +01:00
commit 6bd1f6cc49
25 changed files with 397 additions and 204 deletions

View File

@ -36,9 +36,8 @@ import (
"bytes"
"crypto/ecdsa"
crand "crypto/rand"
"os"
"errors"
"os"
"sync"
"time"
@ -208,3 +207,37 @@ func zeroKey(k *ecdsa.PrivateKey) {
b[i] = 0
}
}
// USE WITH CAUTION = this will save an unencrypted private key on disk
// no cli or js interface
func (am *Manager) Export(path string, addr []byte, keyAuth string) error {
key, err := am.keyStore.GetKey(addr, keyAuth)
if err != nil {
return err
}
return crypto.SaveECDSA(path, key.PrivateKey)
}
func (am *Manager) Import(path string, keyAuth string) (Account, error) {
privateKeyECDSA, err := crypto.LoadECDSA(path)
if err != nil {
return Account{}, err
}
key := crypto.NewKeyFromECDSA(privateKeyECDSA)
if err = am.keyStore.StoreKey(key, keyAuth); err != nil {
return Account{}, err
}
return Account{Address: key.Address}, nil
}
func (am *Manager) ImportPreSaleKey(keyJSON []byte, password string) (acc Account, err error) {
var key *crypto.Key
key, err = crypto.ImportPreSaleKey(am.keyStore, keyJSON, password)
if err != nil {
return
}
if err = am.keyStore.StoreKey(key, password); err != nil {
return
}
return Account{Address: key.Address}, nil
}

View File

@ -1,7 +1,7 @@
package blockpool
import (
// "fmt"
"fmt"
"testing"
"time"
@ -45,17 +45,15 @@ func getStatusValues(s *Status) []int {
func checkStatus(t *testing.T, bp *BlockPool, syncing bool, expected []int) (err error) {
s := bp.Status()
if s.Syncing != syncing {
t.Errorf("status for Syncing incorrect. expected %v, got %v", syncing, s.Syncing)
err = fmt.Errorf("status for Syncing incorrect. expected %v, got %v", syncing, s.Syncing)
return
}
got := getStatusValues(s)
for i, v := range expected {
if i == 0 || i == 7 {
continue //hack
}
err = test.CheckInt(statusFields[i], got[i], v, t)
// fmt.Printf("%v: %v (%v)\n", statusFields[i], got[i], v)
if err != nil {
return err
return
}
}
return
@ -63,6 +61,25 @@ func checkStatus(t *testing.T, bp *BlockPool, syncing bool, expected []int) (err
func TestBlockPoolStatus(t *testing.T) {
test.LogInit()
var err error
n := 3
for n > 0 {
n--
err = testBlockPoolStatus(t)
if err != nil {
t.Log(err)
continue
} else {
return
}
}
if err != nil {
t.Errorf("no pass out of 3: %v", err)
}
}
func testBlockPoolStatus(t *testing.T) (err error) {
_, blockPool, blockPoolTester := newTestBlockPool(t)
blockPoolTester.blockChain[0] = nil
blockPoolTester.initRefBlockChain(12)
@ -70,6 +87,7 @@ func TestBlockPoolStatus(t *testing.T) {
delete(blockPoolTester.refBlockChain, 6)
blockPool.Start()
defer blockPool.Stop()
blockPoolTester.tds = make(map[int]int)
blockPoolTester.tds[9] = 1
blockPoolTester.tds[11] = 3
@ -79,73 +97,67 @@ func TestBlockPoolStatus(t *testing.T) {
peer2 := blockPoolTester.newPeer("peer2", 2, 6)
peer3 := blockPoolTester.newPeer("peer3", 3, 11)
peer4 := blockPoolTester.newPeer("peer4", 1, 9)
// peer1 := blockPoolTester.newPeer("peer1", 1, 9)
// peer2 := blockPoolTester.newPeer("peer2", 2, 6)
// peer3 := blockPoolTester.newPeer("peer3", 3, 11)
// peer4 := blockPoolTester.newPeer("peer4", 1, 9)
peer2.blocksRequestsMap = peer1.blocksRequestsMap
var expected []int
var err error
expected = []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
err = checkStatus(t, blockPool, false, expected)
err = checkStatus(nil, blockPool, false, expected)
if err != nil {
return
}
peer1.AddPeer()
expected = []int{0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlocks(8, 9)
expected = []int{0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
// err = checkStatus(t, blockPool, true, expected)
expected = []int{1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlockHashes(9, 8, 7, 3, 2)
expected = []int{6, 5, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
// expected = []int{5, 5, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlocks(3, 7, 8)
expected = []int{6, 5, 3, 3, 0, 1, 0, 0, 1, 1, 1, 1, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlocks(2, 3)
expected = []int{6, 5, 4, 4, 0, 1, 0, 0, 1, 1, 1, 1, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer4.AddPeer()
expected = []int{6, 5, 4, 4, 0, 2, 0, 0, 2, 2, 1, 1, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer4.sendBlockHashes(12, 11)
expected = []int{6, 5, 4, 4, 0, 2, 0, 0, 2, 2, 1, 1, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer2.AddPeer()
expected = []int{6, 5, 4, 4, 0, 3, 0, 0, 3, 3, 1, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
@ -153,76 +165,76 @@ func TestBlockPoolStatus(t *testing.T) {
peer2.serveBlocks(5, 6)
peer2.serveBlockHashes(6, 5, 4, 3, 2)
expected = []int{10, 8, 5, 5, 0, 3, 1, 0, 3, 3, 2, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer2.serveBlocks(2, 3, 4)
expected = []int{10, 8, 6, 6, 0, 3, 1, 0, 3, 3, 2, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
blockPool.RemovePeer("peer2")
expected = []int{10, 8, 6, 6, 0, 3, 1, 0, 3, 2, 2, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlockHashes(2, 1, 0)
expected = []int{11, 9, 6, 6, 0, 3, 1, 0, 3, 2, 2, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlocks(1, 2)
expected = []int{11, 9, 7, 7, 0, 3, 1, 0, 3, 2, 2, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer1.serveBlocks(4, 5)
expected = []int{11, 9, 8, 8, 0, 3, 1, 0, 3, 2, 2, 2, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer3.AddPeer()
expected = []int{11, 9, 8, 8, 0, 4, 1, 0, 4, 3, 2, 3, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer3.serveBlocks(10, 11)
expected = []int{12, 9, 9, 9, 0, 4, 1, 0, 4, 3, 3, 3, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer3.serveBlockHashes(11, 10, 9)
expected = []int{14, 11, 9, 9, 0, 4, 1, 0, 4, 3, 3, 3, 0}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer4.sendBlocks(11, 12)
expected = []int{14, 11, 9, 9, 0, 4, 1, 0, 4, 3, 4, 3, 1}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
peer3.serveBlocks(9, 10)
expected = []int{14, 11, 10, 10, 0, 4, 1, 0, 4, 3, 4, 3, 1}
err = checkStatus(t, blockPool, true, expected)
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
return
}
@ -231,10 +243,9 @@ func TestBlockPoolStatus(t *testing.T) {
blockPool.Wait(waitTimeout)
time.Sleep(200 * time.Millisecond)
expected = []int{14, 3, 11, 3, 8, 4, 1, 8, 4, 3, 4, 3, 1}
err = checkStatus(t, blockPool, false, expected)
err = checkStatus(nil, blockPool, false, expected)
if err != nil {
return
}
blockPool.Stop()
return nil
}

View File

@ -10,16 +10,20 @@ import (
func CheckInt(name string, got int, expected int, t *testing.T) (err error) {
if got != expected {
t.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
err = fmt.Errorf("")
err = fmt.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
if t != nil {
t.Error(err)
}
}
return
}
func CheckDuration(name string, got time.Duration, expected time.Duration, t *testing.T) (err error) {
if got != expected {
t.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
err = fmt.Errorf("")
err = fmt.Errorf("status for %v incorrect. expected %v, got %v", name, expected, got)
if t != nil {
t.Error(err)
}
}
return
}

View File

@ -67,14 +67,14 @@ type jsre struct {
prompter
}
func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre {
func newJSRE(ethereum *eth.Ethereum, libPath string, interactive bool) *jsre {
js := &jsre{ethereum: ethereum, ps1: "> "}
js.xeth = xeth.New(ethereum, js)
js.re = re.New(libPath)
js.apiBindings()
js.adminBindings()
if !liner.TerminalSupported() {
if !liner.TerminalSupported() || !interactive {
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
} else {
lr := liner.NewLiner()
@ -102,7 +102,7 @@ func (js *jsre) apiBindings() {
jethObj := t.Object()
jethObj.Set("send", jeth.Send)
err := js.re.Compile("bignum.js", re.BigNumber_JS)
err := js.re.Compile("bignumber.js", re.BigNumber_JS)
if err != nil {
utils.Fatalf("Error loading bignumber.js: %v", err)
}

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"path"
"testing"
@ -9,7 +10,6 @@ import (
"github.com/robertkrimen/otto"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
)
@ -30,8 +30,8 @@ func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) {
}
// FIXME: this does not work ATM
ks := crypto.NewKeyStorePlain("/tmp/eth/keys")
common.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d",
[]byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`))
ioutil.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d",
[]byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`), os.ModePerm)
port++
ethereum, err = eth.New(&eth.Config{
@ -47,7 +47,7 @@ func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) {
return
}
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
repl = newJSRE(ethereum, assetPath)
repl = newJSRE(ethereum, assetPath, false)
return
}

View File

@ -23,14 +23,15 @@ package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"runtime"
"strconv"
"strings"
"time"
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
@ -41,8 +42,8 @@ import (
)
const (
ClientIdentifier = "Ethereum(G)"
Version = "0.9.3"
ClientIdentifier = "Geth"
Version = "0.9.4"
)
var (
@ -74,10 +75,44 @@ Regular users do not need to execute it.
The output of this command is supposed to be machine-readable.
`,
},
{
Name: "wallet",
Usage: "ethereum presale wallet",
Subcommands: []cli.Command{
{
Action: importWallet,
Name: "import",
Usage: "import ethereum presale wallet",
},
},
},
{
Action: accountList,
Name: "account",
Usage: "manage accounts",
Description: `
Manage accounts lets you create new accounts, list all existing accounts,
import a private key into a new account.
It supports interactive mode, when you are prompted for password as well as
non-interactive mode where passwords are supplied via a given password file.
Non-interactive mode is only meant for scripted use on test networks or known
safe environments.
Make sure you remember the password you gave when creating a new account (with
either new or import). Without it you are not able to unlock your account.
Note that exporting your key in unencrypted format is NOT supported.
Keys are stored under <DATADIR>/keys.
It is safe to transfer the entire directory or the individual keys therein
between ethereum nodes.
Make sure you backup your keys regularly.
And finally. DO NOT FORGET YOUR PASSWORD.
`,
Subcommands: []cli.Command{
{
Action: accountList,
@ -88,6 +123,51 @@ The output of this command is supposed to be machine-readable.
Action: accountCreate,
Name: "new",
Usage: "create a new account",
Description: `
ethereum account new
Creates a new account. Prints the address.
The account is saved in encrypted format, you are prompted for a passphrase.
You must remember this passphrase to unlock your account in the future.
For non-interactive use the passphrase can be specified with the --password flag:
ethereum --password <passwordfile> account new
Note, this is meant to be used for testing only, it is a bad idea to save your
password to file or expose in any other way.
`,
},
{
Action: accountImport,
Name: "import",
Usage: "import a private key into a new account",
Description: `
ethereum account import <keyfile>
Imports an unencrypted private key from <keyfile> and creates a new account.
Prints the address.
The keyfile is assumed to contain an unencrypted private key in canonical EC
raw bytes format.
The account is saved in encrypted format, you are prompted for a passphrase.
You must remember this passphrase to unlock your account in the future.
For non-interactive use the passphrase can be specified with the -password flag:
ethereum --password <passwordfile> account import <keyfile>
Note:
As you can directly copy your encrypted accounts to another ethereum instance,
this import mechanism is not needed when you transfer an account between
nodes.
`,
},
},
},
@ -103,18 +183,20 @@ Use "ethereum dump 0" to dump the genesis block.
{
Action: console,
Name: "console",
Usage: `Ethereum Console: interactive JavaScript environment`,
Usage: `Geth Console: interactive JavaScript environment`,
Description: `
Console is an interactive shell for the Ethereum JavaScript runtime environment which exposes a node admin interface as well as the DAPP JavaScript API.
The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the DAPP JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
`,
},
{
Action: execJSFiles,
Name: "js",
Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
Usage: `executes the given JavaScript files in the Geth JavaScript VM`,
Description: `
The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
The JavaScript VM exposes a node admin interface as well as the DAPP
JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
`,
},
{
@ -130,6 +212,7 @@ The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP Ja
}
app.Flags = []cli.Flag{
utils.UnlockedAccountFlag,
utils.PasswordFileFlag,
utils.BootnodesFlag,
utils.DataDirFlag,
utils.JSpathFlag,
@ -146,7 +229,6 @@ The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP Ja
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.UnencryptedKeysFlag,
utils.VMDebugFlag,
utils.ProtocolVersionFlag,
utils.NetworkIdFlag,
@ -194,7 +276,7 @@ func console(ctx *cli.Context) {
}
startEth(ctx, ethereum)
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name), true)
repl.interactive()
ethereum.Stop()
@ -209,7 +291,7 @@ func execJSFiles(ctx *cli.Context) {
}
startEth(ctx, ethereum)
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name), false)
for _, file := range ctx.Args() {
repl.exec(file)
}
@ -218,22 +300,36 @@ func execJSFiles(ctx *cli.Context) {
ethereum.WaitForShutdown()
}
func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (passphrase string) {
var err error
// Load startup keys. XXX we are going to need a different format
// Attempt to unlock the account
passphrase = getPassPhrase(ctx, "", false)
accbytes := common.FromHex(account)
if len(accbytes) == 0 {
utils.Fatalf("Invalid account address '%s'", account)
}
err = am.Unlock(accbytes, passphrase)
if err != nil {
utils.Fatalf("Unlock account failed '%v'", err)
}
return
}
func startEth(ctx *cli.Context, eth *eth.Ethereum) {
utils.StartEthereum(eth)
am := eth.AccountManager()
// Load startup keys. XXX we are going to need a different format
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
if len(account) > 0 {
split := strings.Split(account, ":")
if len(split) != 2 {
utils.Fatalf("Illegal 'unlock' format (address:password)")
}
am := eth.AccountManager()
// Attempt to unlock the account
err := am.Unlock(common.FromHex(split[0]), split[1])
if err != nil {
utils.Fatalf("Unlock account failed '%v'", err)
if account == "coinbase" {
accbytes, err := am.Coinbase()
if err != nil {
utils.Fatalf("no coinbase account: %v", err)
}
account = common.ToHex(accbytes)
}
unlockAccount(ctx, am, account)
}
// Start auxiliary services if enabled.
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
@ -255,30 +351,77 @@ func accountList(ctx *cli.Context) {
}
}
func accountCreate(ctx *cli.Context) {
am := utils.GetAccountManager(ctx)
passphrase := ""
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
fmt.Println("The new account will be encrypted with a passphrase.")
fmt.Println("Please enter a passphrase now.")
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase string) {
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
if len(passfile) == 0 {
fmt.Println(desc)
auth, err := readPassword("Passphrase: ", true)
if err != nil {
utils.Fatalf("%v", err)
}
confirm, err := readPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
if auth != confirm {
utils.Fatalf("Passphrases did not match.")
if confirmation {
confirm, err := readPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
if auth != confirm {
utils.Fatalf("Passphrases did not match.")
}
}
passphrase = auth
} else {
passbytes, err := ioutil.ReadFile(passfile)
if err != nil {
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
}
passphrase = string(passbytes)
}
return
}
func accountCreate(ctx *cli.Context) {
am := utils.GetAccountManager(ctx)
passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true)
acct, err := am.NewAccount(passphrase)
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}
fmt.Printf("Address: %x\n", acct.Address)
fmt.Printf("Address: %x\n", acct)
}
func importWallet(ctx *cli.Context) {
keyfile := ctx.Args().First()
if len(keyfile) == 0 {
utils.Fatalf("keyfile must be given as argument")
}
keyJson, err := ioutil.ReadFile(keyfile)
if err != nil {
utils.Fatalf("Could not read wallet file: %v", err)
}
am := utils.GetAccountManager(ctx)
passphrase := getPassPhrase(ctx, "", false)
acct, err := am.ImportPreSaleKey(keyJson, passphrase)
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}
fmt.Printf("Address: %x\n", acct)
}
func accountImport(ctx *cli.Context) {
keyfile := ctx.Args().First()
if len(keyfile) == 0 {
utils.Fatalf("keyfile must be given as argument")
}
am := utils.GetAccountManager(ctx)
passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true)
acct, err := am.Import(keyfile, passphrase)
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}
fmt.Printf("Address: %x\n", acct)
}
func importchain(ctx *cli.Context) {

@ -1 +1 @@
Subproject commit 9f073d9091cd2d2b46dd46afea9dcf5d825ecd7c
Subproject commit 17164bea8b330d6a118b40d6fbe222ffb12a0e9f

View File

@ -22,13 +22,14 @@ package main
import (
"encoding/json"
"io/ioutil"
"os"
"strconv"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
)
type plugin struct {
@ -46,14 +47,14 @@ func (self *Gui) AddPlugin(pluginPath string) {
self.plugins[pluginPath] = plugin{Name: pluginPath, Path: pluginPath}
json, _ := json.MarshalIndent(self.plugins, "", " ")
common.WriteFile(self.eth.DataDir+"/plugins.json", json)
ioutil.WriteFile(self.eth.DataDir+"/plugins.json", json, os.ModePerm)
}
func (self *Gui) RemovePlugin(pluginPath string) {
delete(self.plugins, pluginPath)
json, _ := json.MarshalIndent(self.plugins, "", " ")
common.WriteFile(self.eth.DataDir+"/plugins.json", json)
ioutil.WriteFile(self.eth.DataDir+"/plugins.json", json, os.ModePerm)
}
func (self *Gui) DumpState(hash, path string) {

View File

@ -25,6 +25,7 @@ import "C"
import (
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"path"
"runtime"
@ -91,8 +92,8 @@ func NewWindow(ethereum *eth.Ethereum) *Gui {
plugins: make(map[string]plugin),
serviceEvents: make(chan ServEv, 1),
}
data, _ := common.ReadAllFile(path.Join(ethereum.DataDir, "plugins.json"))
json.Unmarshal([]byte(data), &gui.plugins)
data, _ := ioutil.ReadFile(path.Join(ethereum.DataDir, "plugins.json"))
json.Unmarshal(data, &gui.plugins)
return gui
}

View File

@ -97,14 +97,15 @@ var (
Usage: "Enable mining",
}
// key settings
UnencryptedKeysFlag = cli.BoolFlag{
Name: "unencrypted-keys",
Usage: "disable private key disk encryption (for testing)",
}
UnlockedAccountFlag = cli.StringFlag{
Name: "unlock",
Usage: "Unlock a given account untill this programs exits (address:password)",
Usage: "unlock the account given until this program exits (prompts for password). '--unlock coinbase' unlocks the primary (coinbase) account",
Value: "",
}
PasswordFileFlag = cli.StringFlag{
Name: "password",
Usage: "Path to password file for (un)locking an existing account.",
Value: "",
}
// logging and debug settings
@ -243,12 +244,7 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
dataDir := ctx.GlobalString(DataDirFlag.Name)
var ks crypto.KeyStore2
if ctx.GlobalBool(UnencryptedKeysFlag.Name) {
ks = crypto.NewKeyStorePlain(path.Join(dataDir, "plainkeys"))
} else {
ks = crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
}
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
return accounts.NewManager(ks)
}

View File

@ -2,7 +2,6 @@ package common
import (
"fmt"
"io/ioutil"
"os"
"os/user"
"path"
@ -43,35 +42,6 @@ func FileExist(filePath string) bool {
return true
}
func ReadAllFile(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
data, err := ioutil.ReadAll(file)
if err != nil {
return "", err
}
return string(data), nil
}
func WriteFile(filePath string, content []byte) error {
fh, err := os.OpenFile(filePath, os.O_TRUNC|os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
return err
}
defer fh.Close()
_, err = fh.Write(content)
if err != nil {
return err
}
return nil
}
func AbsolutePath(Datadir string, filename string) string {
if path.IsAbs(filename) {
return filename

View File

@ -2,56 +2,11 @@ package common
import (
"os"
"testing"
// "testing"
checker "gopkg.in/check.v1"
)
func TestGoodFile(t *testing.T) {
goodpath := "~/goethereumtest.pass"
path := ExpandHomePath(goodpath)
contentstring := "3.14159265358979323846"
err := WriteFile(path, []byte(contentstring))
if err != nil {
t.Error("Could not write file")
}
if !FileExist(path) {
t.Error("File not found at", path)
}
v, err := ReadAllFile(path)
if err != nil {
t.Error("Could not read file", path)
}
if v != contentstring {
t.Error("Expected", contentstring, "Got", v)
}
}
func TestBadFile(t *testing.T) {
badpath := "/this/path/should/not/exist/goethereumtest.fail"
path := ExpandHomePath(badpath)
contentstring := "3.14159265358979323846"
err := WriteFile(path, []byte(contentstring))
if err == nil {
t.Error("Wrote file, but should not be able to", path)
}
if FileExist(path) {
t.Error("Found file, but should not be able to", path)
}
v, err := ReadAllFile(path)
if err == nil {
t.Error("Read file, but should not be able to", v)
}
}
type CommonSuite struct{}
var _ = checker.Suite(&CommonSuite{})

View File

@ -4,8 +4,8 @@ import (
"math"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
)
type AccountChange struct {

View File

@ -5,6 +5,8 @@ import (
"math/big"
)
const maxStack = 1024
func newStack() *stack {
return &stack{}
}
@ -15,6 +17,10 @@ type stack struct {
}
func (st *stack) push(d *big.Int) {
if len(st.data) == maxStack {
panic(fmt.Sprintf("stack limit reached (%d)", maxStack))
}
stackItem := new(big.Int).Set(d)
if len(st.data) > st.ptr {
st.data[st.ptr] = stackItem

View File

@ -9,6 +9,7 @@ import (
"crypto/sha256"
"fmt"
"io"
"io/ioutil"
"os"
"encoding/hex"
@ -139,6 +140,12 @@ func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
return ToECDSA(buf), nil
}
// SaveECDSA saves a secp256k1 private key to the given file with restrictive
// permissions
func SaveECDSA(file string, key *ecdsa.PrivateKey) error {
return ioutil.WriteFile(file, FromECDSA(key), 0600)
}
func GenerateKey() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(S256(), rand.Reader)
}

View File

@ -85,6 +85,16 @@ func (k *Key) UnmarshalJSON(j []byte) (err error) {
return err
}
func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
id := uuid.NewRandom()
key := &Key{
Id: id,
Address: PubkeyToAddress(privateKeyECDSA.PublicKey),
PrivateKey: privateKeyECDSA,
}
return key
}
func NewKey(rand io.Reader) *Key {
randBytes := make([]byte, 64)
_, err := rand.Read(randBytes)
@ -97,11 +107,5 @@ func NewKey(rand io.Reader) *Key {
panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
}
id := uuid.NewRandom()
key := &Key{
Id: id,
Address: PubkeyToAddress(privateKeyECDSA.PublicKey),
PrivateKey: privateKeyECDSA,
}
return key
return NewKeyFromECDSA(privateKeyECDSA)
}

File diff suppressed because one or more lines are too long

View File

@ -2,9 +2,9 @@ package jsre
import (
"github.com/robertkrimen/otto"
"io/ioutil"
"os"
"testing"
"github.com/ethereum/go-ethereum/common"
)
type testNativeObjectBinding struct {
@ -26,7 +26,7 @@ func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value
func TestExec(t *testing.T) {
jsre := New("/tmp")
common.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
ioutil.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`), os.ModePerm)
err := jsre.Exec("test.js")
if err != nil {
t.Errorf("expected no error, got %v", err)
@ -64,7 +64,7 @@ func TestBind(t *testing.T) {
func TestLoadScript(t *testing.T) {
jsre := New("/tmp")
common.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
ioutil.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`), os.ModePerm)
_, err := jsre.Run(`loadScript("test.js")`)
if err != nil {
t.Errorf("expected no error, got %v", err)

View File

@ -1,12 +1,15 @@
package miner
import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/pow"
)
type CpuMiner struct {
chMu sync.Mutex
c chan *types.Block
quit chan struct{}
quitCurrentOp chan struct{}
@ -43,16 +46,13 @@ func (self *CpuMiner) Start() {
}
func (self *CpuMiner) update() {
justStarted := true
out:
for {
select {
case block := <-self.c:
if justStarted {
justStarted = true
} else {
self.quitCurrentOp <- struct{}{}
}
self.chMu.Lock()
self.quitCurrentOp <- struct{}{}
self.chMu.Unlock()
go self.mine(block)
case <-self.quit:
@ -60,6 +60,7 @@ out:
}
}
close(self.quitCurrentOp)
done:
// Empty channel
for {
@ -75,12 +76,20 @@ done:
func (self *CpuMiner) mine(block *types.Block) {
minerlogger.Debugf("(re)started agent[%d]. mining...\n", self.index)
// Reset the channel
self.chMu.Lock()
self.quitCurrentOp = make(chan struct{}, 1)
self.chMu.Unlock()
// Mine
nonce, mixDigest, _ := self.pow.Search(block, self.quitCurrentOp)
if nonce != 0 {
block.SetNonce(nonce)
block.Header().MixDigest = common.BytesToHash(mixDigest)
self.returnCh <- block
//self.returnCh <- Work{block.Number().Uint64(), nonce, mixDigest, seedHash}
} else {
self.returnCh <- nil
}
}

View File

@ -50,6 +50,7 @@ out:
break out
case work := <-a.workCh:
a.work = work
a.returnCh <- nil
}
}
}

View File

@ -5,6 +5,7 @@ import (
"math/big"
"sort"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@ -58,13 +59,14 @@ type Agent interface {
}
type worker struct {
mu sync.Mutex
mu sync.Mutex
agents []Agent
recv chan *types.Block
mux *event.TypeMux
quit chan struct{}
pow pow.PoW
atWork int
atWork int64
eth core.Backend
chain *core.ChainManager
@ -107,7 +109,7 @@ func (self *worker) start() {
func (self *worker) stop() {
self.mining = false
self.atWork = 0
atomic.StoreInt64(&self.atWork, 0)
close(self.quit)
}
@ -135,9 +137,6 @@ out:
self.uncleMu.Unlock()
}
if self.atWork == 0 {
self.commitNewWork()
}
case <-self.quit:
// stop all agents
for _, agent := range self.agents {
@ -146,6 +145,11 @@ out:
break out
case <-timer.C:
minerlogger.Infoln("Hash rate:", self.HashRate(), "Khash")
// XXX In case all mined a possible uncle
if atomic.LoadInt64(&self.atWork) == 0 {
self.commitNewWork()
}
}
}
@ -155,6 +159,12 @@ out:
func (self *worker) wait() {
for {
for block := range self.recv {
atomic.AddInt64(&self.atWork, -1)
if block == nil {
continue
}
if err := self.chain.InsertChain(types.Blocks{block}); err == nil {
for _, uncle := range block.Uncles() {
delete(self.possibleUncles, uncle.Hash())
@ -170,7 +180,6 @@ func (self *worker) wait() {
} else {
self.commitNewWork()
}
self.atWork--
}
}
}
@ -182,8 +191,9 @@ func (self *worker) push() {
// push new work to agents
for _, agent := range self.agents {
atomic.AddInt64(&self.atWork, 1)
agent.Work() <- self.current.block.Copy()
self.atWork++
}
}
}

View File

@ -3,6 +3,8 @@ package rpc
import (
"bytes"
"encoding/json"
// "errors"
// "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -60,6 +62,26 @@ func numString(raw interface{}, number *int64) error {
return nil
}
// func toNumber(v interface{}) (int64, error) {
// var str string
// if v != nil {
// var ok bool
// str, ok = v.(string)
// if !ok {
// return 0, errors.New("is not a string or undefined")
// }
// } else {
// str = "latest"
// }
// switch str {
// case "latest":
// return -1, nil
// default:
// return int64(common.Big(v.(string)).Int64()), nil
// }
// }
type GetBlockByHashArgs struct {
BlockHash string
IncludeTxs bool
@ -442,6 +464,14 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
// args.Earliest, err = toNumber(obj[0].ToBlock)
// if err != nil {
// return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
// }
// args.Latest, err = toNumber(obj[0].FromBlock)
// if err != nil {
// return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
var num int64
if err := blockHeight(obj[0].FromBlock, &num); err != nil {
return err
@ -464,6 +494,7 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
if err := numString(obj[0].Offset, &num); err != nil {
return err
}
args.Skip = int(num)

View File

@ -9,5 +9,16 @@
"full_size": 1073739904,
"header_hash": "2a8de2adf89af77358250bf908bf04ba94a6e8c3ba87775564a41d269a05e4ce",
"cache_hash": "35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353"
},
"second": {
"nonce": "307692cf71b12f6d",
"mixhash": "e55d02c555a7969361cf74a9ec6211d8c14e4517930a00442f171bdb1698d175",
"header": "f901f7a01bef91439a3e070a6586851c11e6fd79bbbea074b2b836727b8e75c7d4a6b698a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea3cb5f94fa2ddd52ec6dd6eb75cf824f4058ca1a00c6e51346be0670ce63ac5f05324e27d20b180146269c5aab844d09a2b108c64a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd880845511ed2a80a0e55d02c555a7969361cf74a9ec6211d8c14e4517930a00442f171bdb1698d17588307692cf71b12f6d",
"seed": "0000000000000000000000000000000000000000000000000000000000000000",
"result": "ab9b13423cface72cbec8424221651bc2e384ef0f7a560e038fc68c8d8684829",
"cache_size": 16776896,
"full_size": 1073739904,
"header_hash": "100cbec5e5ef82991290d0d93d758f19082e71f234cf479192a8b94df6da6bfe",
"cache_hash": "35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353"
}
}