diff --git a/accounts/account_manager.go b/accounts/account_manager.go index 646dc8376e..34a2c48910 100644 --- a/accounts/account_manager.go +++ b/accounts/account_manager.go @@ -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 +} diff --git a/blockpool/status_test.go b/blockpool/status_test.go index cbaa8bb559..a87b99d7c9 100644 --- a/blockpool/status_test.go +++ b/blockpool/status_test.go @@ -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 } diff --git a/blockpool/test/util.go b/blockpool/test/util.go index 0349493c31..930601278b 100644 --- a/blockpool/test/util.go +++ b/blockpool/test/util.go @@ -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 } diff --git a/cmd/ethereum/admin.go b/cmd/geth/admin.go similarity index 100% rename from cmd/ethereum/admin.go rename to cmd/geth/admin.go diff --git a/cmd/ethereum/blocktest.go b/cmd/geth/blocktest.go similarity index 100% rename from cmd/ethereum/blocktest.go rename to cmd/geth/blocktest.go diff --git a/cmd/ethereum/js.go b/cmd/geth/js.go similarity index 96% rename from cmd/ethereum/js.go rename to cmd/geth/js.go index 1f0033daa7..8e88a1c543 100644 --- a/cmd/ethereum/js.go +++ b/cmd/geth/js.go @@ -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) } diff --git a/cmd/ethereum/js_test.go b/cmd/geth/js_test.go similarity index 97% rename from cmd/ethereum/js_test.go rename to cmd/geth/js_test.go index a6058b3184..5b962f6219 100644 --- a/cmd/ethereum/js_test.go +++ b/cmd/geth/js_test.go @@ -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(ð.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 } diff --git a/cmd/ethereum/main.go b/cmd/geth/main.go similarity index 59% rename from cmd/ethereum/main.go rename to cmd/geth/main.go index 2cf81b9e75..da505218bc 100644 --- a/cmd/ethereum/main.go +++ b/cmd/geth/main.go @@ -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 /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 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 + +Imports an unencrypted private key from 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 account import + +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) { diff --git a/cmd/mist/assets/ext/ethereum.js b/cmd/mist/assets/ext/ethereum.js index 9f073d9091..17164bea8b 160000 --- a/cmd/mist/assets/ext/ethereum.js +++ b/cmd/mist/assets/ext/ethereum.js @@ -1 +1 @@ -Subproject commit 9f073d9091cd2d2b46dd46afea9dcf5d825ecd7c +Subproject commit 17164bea8b330d6a118b40d6fbe222ffb12a0e9f diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go index 8a9ec7cb17..e7ce50c352 100644 --- a/cmd/mist/bindings.go +++ b/cmd/mist/bindings.go @@ -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) { diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go index 08f02f833a..d37d6f81b8 100644 --- a/cmd/mist/gui.go +++ b/cmd/mist/gui.go @@ -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 } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 94b043d730..f948cdb06b 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -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) } diff --git a/common/path.go b/common/path.go index d38b1fd5b3..a74a0d5bd3 100644 --- a/common/path.go +++ b/common/path.go @@ -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 diff --git a/common/path_test.go b/common/path_test.go index c831d1a57d..4b90c543b7 100644 --- a/common/path_test.go +++ b/common/path_test.go @@ -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{}) diff --git a/core/filter.go b/core/filter.go index 901931d991..ba5d5e14e7 100644 --- a/core/filter.go +++ b/core/filter.go @@ -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 { diff --git a/core/vm/stack.go b/core/vm/stack.go index c5c2774db0..1e093476bf 100644 --- a/core/vm/stack.go +++ b/core/vm/stack.go @@ -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 diff --git a/crypto/crypto.go b/crypto/crypto.go index c3d47b6293..442942c6c5 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -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) } diff --git a/crypto/key.go b/crypto/key.go index 9dbf374675..0b84bfec16 100644 --- a/crypto/key.go +++ b/crypto/key.go @@ -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) } diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go index fb01702888..403c438bc8 100644 --- a/jsre/ethereum_js.go +++ b/jsre/ethereum_js.go @@ -1,3 +1,3 @@ package jsre -const Ethereum_JS = `require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ay;y++)g.push(d(e.slice(0,u))),e=e.slice(u);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(u),n.push(d(e.slice(0,u))),e=e.slice(u)):(n.push(d(e.slice(0,u))),e=e.slice(u))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),i(r.toTwosComplement(t).round().toString(16),e)},s=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},u=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},c=function(t){return a(new n(t).times(new n(2).pow(128)))},l=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},f=function(t){return t=t||"0",l(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},p=function(t){return t=t||"0",new n(t,16)},m=function(t){return f(t).dividedBy(new n(2).pow(128))},d=function(t){return p(t).dividedBy(new n(2).pow(128))},h=function(t){return"0x"+t},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},y=function(t){return r.toAscii(t)},v=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:s,formatInputBool:u,formatInputReal:c,formatOutputInt:f,formatOutputUInt:p,formatOutputReal:m,formatOutputUReal:d,formatOutputHash:h,formatOutputBool:g,formatOutputString:y,formatOutputAddress:v}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},a=function(t){for(var e="",n=0;n1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},e.exports=o},{"../utils/utils":6,"./errors":11}],19:[function(t,e){var n=t("../utils/utils"),r=t("./property"),o=[],i=[new r({name:"listening",getter:"net_listening"}),new r({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:o,properties:i}},{"../utils/utils":6,"./property":20}],20:[function(t,e){var n=(t("../utils/utils"),t("./errors"),function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter});n.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},n.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},n.prototype.attachToObject=function(t,e){var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},e.exports=n},{"../utils/utils":6,"./errors":11}],21:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],22:[function(t,e){var n=t("./jsonrpc"),r=t("../utils/utils"),o=t("../utils/config"),i=t("./errors"),a=function(t){this.jsonrpc=new n,this.provider=t,this.polls=[],this.timeout=null,this.poll()};a.prototype.send=function(t){if(!this.provider)return console.error(i.InvalidProvider),null;var e=this.jsonrpc.toPayload(t.method,t.params),n=this.provider.send(e);if(!this.jsonrpc.isValidResponse(n))throw i.InvalidResponse(n);return n.result},a.prototype.sendAsync=function(t,e){if(!this.provider)return e(i.InvalidProvider);var n=this.jsonrpc.toPayload(t.method,t.params),r=this;this.provider.sendAsync(n,function(t,n){return t?e(t):r.jsonrpc.isValidResponse(n)?void e(null,n.result):e(i.InvalidResponse(n))})},a.prototype.setProvider=function(t){this.provider=t},a.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},a.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},a.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},a.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(i.InvalidProvider);var t=this.jsonrpc.toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,n){if(!t){if(!r.isArray(n))throw i.InvalidResponse(n);n.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var n=e.jsonrpc.isValidResponse(t);return n||t.callback(i.InvalidResponse(t)),n}).filter(function(t){return r.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t)})}})}},e.exports=a},{"../utils/config":5,"../utils/utils":6,"./errors":11,"./jsonrpc":17}],23:[function(t,e){var n=t("./method"),r=t("./formatters"),o=new n({name:"post",call:"shh_post",params:1,inputFormatter:r.inputPostFormatter}),i=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),a=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),s=new n({name:"newGroup",call:"shh_newGroup",params:0}),u=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),c=[o,i,a,s,u];e.exports={methods:c}},{"./formatters":15,"./method":18}],24:[function(t,e){var n=t("../web3"),r=t("../utils/config"),o=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*r.ETH_SIGNATURE_LENGTH)},i=function(t){return n.sha3(n.fromAscii(t))};e.exports={functionSignatureFromAscii:o,eventSignatureFromAscii:i}},{"../utils/config":5,"../web3":8}],25:[function(t,e){var n=t("./method"),r=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1});return[e,r,o]},o=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1});return[t,e,r]};e.exports={eth:r,shh:o}},{"./method":18}],26:[function(){},{}],"bignumber.js":[function(t,e){"use strict";e.exports=BigNumber},{}],"ethereum.js":[function(t,e){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":8,"./lib/web3/contract":9,"./lib/web3/httpprovider":16,"./lib/web3/qtsync":21}]},{},["ethereum.js"]);` +const Ethereum_JS = `require=function t(e,n,r){function o(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ay;y++)g.push(d(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(d(e.slice(0,s))),e=e.slice(s)):(n.push(d(e.slice(0,s))),e=e.slice(s))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),i(r.toTwosComplement(t).round().toString(16),e)},u=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},c=function(t){return a(new n(t).times(new n(2).pow(128)))},l=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},f=function(t){return t=t||"0",l(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},p=function(t){return t=t||"0",new n(t,16)},m=function(t){return f(t).dividedBy(new n(2).pow(128))},d=function(t){return p(t).dividedBy(new n(2).pow(128))},h=function(t){return"0x"+t},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},y=function(t){return r.toAscii(t)},b=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:u,formatInputBool:s,formatInputReal:c,formatOutputInt:f,formatOutputUInt:p,formatOutputReal:m,formatOutputUReal:d,formatOutputHash:h,formatOutputBool:g,formatOutputString:y,formatOutputAddress:b}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},a=function(t){for(var e="",n=0;n1?(t[n[0]]||(t[n[0]]={}),t[n[0]][n[1]]=r):t[n[0]]=r})},g=function(t,e){e.forEach(function(e){var n=e.name.split("."),r={};r.get=function(){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.getter,outputFormatter:e.outputFormatter})},e.setter&&(r.set=function(t){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.setter,params:[t],inputFormatter:e.inputFormatter})}),r.enumerable=!e.newProperty,n.length>1?(t[n[0]]||(t[n[0]]={}),Object.defineProperty(t[n[0]],n[1],r)):Object.defineProperty(t,e.name,r)})},y=function(t,e,n,r){x.manager.startPolling({method:t,params:[e]},e,n,r)},b=function(t){x.manager.stopPolling(t)},v={startPolling:y.bind(null,"eth_getFilterChanges"),stopPolling:b},w={startPolling:y.bind(null,"shh_getFilterChanges"),stopPolling:b},x={version:{api:n.version},manager:f(),providers:{},setProvider:function(t){x.manager.setProvider(t)},reset:function(){x.manager.reset()},toHex:c.toHex,toAscii:c.toAscii,fromAscii:c.fromAscii,toDecimal:c.toDecimal,fromDecimal:c.fromDecimal,toBigNumber:c.toBigNumber,toWei:c.toWei,fromWei:c.fromWei,isAddress:c.isAddress,net:{},eth:{contractFromAbi:function(t){return console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=x.eth.contract(e,t);return n.address=e,n}},filter:function(t,e,n){return t._isEvent?t(e,n):s(t,v,l.outputLogFormatter)},watch:function(t,e,n){return console.warn("eth.watch() is deprecated please use eth.filter() instead."),this.filter(t,e,n)}},db:{},shh:{filter:function(t){return s(t,w,l.outputPostFormatter)},watch:function(t){return console.warn("shh.watch() is deprecated please use shh.filter() instead."),this.filter(t)}}};Object.defineProperty(x.eth,"defaultBlock",{get:function(){return p.ETH_DEFAULTBLOCK},set:function(t){return p.ETH_DEFAULTBLOCK=t,p.ETH_DEFAULTBLOCK}}),h(x,m),g(x,d),h(x.net,r.methods),g(x.net,r.properties),h(x.eth,o.methods),g(x.eth,o.properties),h(x.db,i.methods()),h(x.shh,a.methods()),h(v,u.eth()),h(w,u.shh()),e.exports=x},{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/db":10,"./web3/eth":11,"./web3/filter":13,"./web3/formatters":14,"./web3/net":17,"./web3/requestmanager":19,"./web3/shh":20,"./web3/watches":22}],9:[function(t,e){function n(t,e){t.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return c(n),l(n,t,e),f(n,t,e),p(n,t,e),n}var r=t("../web3"),o=t("../solidity/abi"),i=t("../utils/utils"),a=t("./event"),u=t("./signature"),s=function(t){r._currentContractAbi=t.abi,r._currentContractAddress=t.address,r._currentContractMethodName=t.method,r._currentContractMethodParams=t.params},c=function(t){t.call=function(e){return t._isTransaction=!1,t._options=e,t},t.sendTransaction=function(e){return t._isTransaction=!0,t._options=e,t},t.transact=function(e){return console.warn("myContract.transact() is deprecated please use myContract.sendTransaction() instead."),t.sendTransaction(e)},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},l=function(t,e,n){var a=o.inputParser(e),c=o.outputParser(e);i.filterFunctions(e).forEach(function(o){var l=i.extractDisplayName(o.name),f=i.extractTypeName(o.name),p=function(){var i=Array.prototype.slice.call(arguments),p=u.functionSignatureFromAscii(o.name),m=a[l][f].apply(null,i),d=t._options||{};d.to=n,d.data=p+m;var h=t._isTransaction===!0||t._isTransaction!==!1&&!o.constant,g=d.collapse!==!1;if(t._options={},t._isTransaction=null,h)return s({abi:e,address:n,method:o.name,params:i}),void r.eth.sendTransaction(d);var y=r.eth.call(d),b=c[l][f](y);return g&&(1===b.length?b=b[0]:0===b.length&&(b=null)),b};void 0===t[l]&&(t[l]=p),t[l][f]=p})},f=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=a.outputParser(n);return r(t)},Object.defineProperty(t,"topics",{get:function(){return i.filterEvents(e).map(function(t){return u.eventSignatureFromAscii(t.name)})}})},p=function(t,e,n){i.filterEvents(e).forEach(function(e){var o=function(){var t=Array.prototype.slice.call(arguments),o=u.eventSignatureFromAscii(e.name),i=a.inputParser(n,o,e),s=i.apply(null,t),c=function(t){var n=a.outputParser(e);return n(t)};return r.eth.filter(s,void 0,void 0,c)};o._isEvent=!0;var s=i.extractDisplayName(e.name),c=i.extractTypeName(e.name);void 0===t[s]&&(t[s]=o),t[s][c]=o})},m=function(t){return t instanceof Array&&1===arguments.length?n.bind(null,t):(console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),new n(arguments[1],arguments[0]))};e.exports=m},{"../solidity/abi":1,"../utils/utils":6,"../web3":8,"./event":12,"./signature":21}],10:[function(t,e){var n=function(){return[{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"},{name:"putHex",call:"db_putHex"},{name:"getHex",call:"db_getHex"}]};e.exports={methods:n}},{}],11:[function(t,e){var n=t("./formatters"),r=t("../utils/utils"),o=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockByHash":"eth_getBlockByNumber"},i=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getTransactionByBlockHashAndIndex":"eth_getTransactionByBlockNumberAndIndex"},a=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleByBlockHashAndIndex":"eth_getUncleByBlockNumberAndIndex"},u=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockTransactionCountByHash":"eth_getBlockTransactionCountByNumber"},s=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleCountByBlockHash":"eth_getUncleCountByBlockNumber"},c=[{name:"getBalance",call:"eth_getBalance",addDefaultblock:2,outputFormatter:n.convertToBigNumber},{name:"getStorage",call:"eth_getStorage",addDefaultblock:2},{name:"getStorageAt",call:"eth_getStorageAt",addDefaultblock:3,inputFormatter:r.toHex},{name:"getCode",call:"eth_getCode",addDefaultblock:2},{name:"getBlock",call:o,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,function(t){return t?!0:!1}]},{name:"getUncle",call:a,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,r.toHex,function(t){return t?!0:!1}]},{name:"getCompilers",call:"eth_getCompilers"},{name:"getBlockTransactionCount",call:u,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getBlockUncleCount",call:s,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getTransaction",call:"eth_getTransactionByHash",outputFormatter:n.outputTransactionFormatter},{name:"getTransactionFromBlock",call:i,outputFormatter:n.outputTransactionFormatter,inputFormatter:r.toHex},{name:"getTransactionCount",call:"eth_getTransactionCount",addDefaultblock:2,outputFormatter:r.toDecimal},{name:"sendTransaction",call:"eth_sendTransaction",inputFormatter:n.inputTransactionFormatter},{name:"call",call:"eth_call",addDefaultblock:2,inputFormatter:n.inputCallFormatter},{name:"compile.solidity",call:"eth_compileSolidity"},{name:"compile.lll",call:"eth_compileLLL",inputFormatter:r.toHex},{name:"compile.serpent",call:"eth_compileSerpent",inputFormatter:r.toHex},{name:"flush",call:"eth_flush"},{name:"balanceAt",call:"eth_balanceAt",newMethod:"eth.getBalance"},{name:"stateAt",call:"eth_stateAt",newMethod:"eth.getStorageAt"},{name:"storageAt",call:"eth_storageAt",newMethod:"eth.getStorage"},{name:"countAt",call:"eth_countAt",newMethod:"eth.getTransactionCount"},{name:"codeAt",call:"eth_codeAt",newMethod:"eth.getCode"},{name:"transact",call:"eth_transact",newMethod:"eth.sendTransaction"},{name:"block",call:o,newMethod:"eth.getBlock"},{name:"transaction",call:i,newMethod:"eth.getTransaction"},{name:"uncle",call:a,newMethod:"eth.getUncle"},{name:"compilers",call:"eth_compilers",newMethod:"eth.getCompilers"},{name:"solidity",call:"eth_solidity",newMethod:"eth.compile.solidity"},{name:"lll",call:"eth_lll",newMethod:"eth.compile.lll"},{name:"serpent",call:"eth_serpent",newMethod:"eth.compile.serpent"},{name:"transactionCount",call:u,newMethod:"eth.getBlockTransactionCount"},{name:"uncleCount",call:s,newMethod:"eth.getBlockUncleCount"},{name:"logs",call:"eth_logs"}],l=[{name:"coinbase",getter:"eth_coinbase"},{name:"mining",getter:"eth_mining"},{name:"gasPrice",getter:"eth_gasPrice",outputFormatter:n.convertToBigNumber},{name:"accounts",getter:"eth_accounts"},{name:"blockNumber",getter:"eth_blockNumber",outputFormatter:r.toDecimal},{name:"listening",getter:"net_listening",setter:"eth_setListening",newProperty:"net.listening"},{name:"peerCount",getter:"net_peerCount",newProperty:"net.peerCount"},{name:"number",getter:"eth_number",newProperty:"eth.blockNumber"}];e.exports={methods:c,properties:l}},{"../utils/utils":6,"./formatters":14}],12:[function(t,e){var n=t("../solidity/abi"),r=t("../utils/utils"),o=t("./signature"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},a=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},u=function(t,e){return Object.keys(e).map(function(r){var o=[a(i(t.inputs,!0),r)],u=e[r];return u instanceof Array?u.map(function(t){return n.formatInput(o,[t])}):"0x"+n.formatInput(o,[u])})},s=function(t,e,n){return function(r,o){var i=o||{};return i.address=t,i.topics=[],i.topics.push(e),r&&(i.topics=i.topics.concat(u(n,r))),i}},c=function(t,e,n){var r=e.slice(),o=n.slice();return t.reduce(function(t,e){var n;return n=e.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[e.name]=n,t},{})},l=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,hash:e.hash,args:{}};if(e.topics=e.topic,!e.topics)return o;var a=i(t.inputs,!0),u="0x"+e.topics.slice(1,e.topics.length).map(function(t){return t.slice(2)}).join(""),s=n.formatOutput(a,u),l=i(t.inputs,!1),f=n.formatOutput(l,e.data);return o.args=c(t.inputs,s,f),o}},f=function(t,e){for(var n=0;n