Skip to content

Commit

Permalink
Merge branch 'release/0.9.20'
Browse files Browse the repository at this point in the history
  • Loading branch information
obscuren committed May 12, 2015
2 parents 7d69679 + 8fe01b4 commit 8e24378
Show file tree
Hide file tree
Showing 54 changed files with 4,653 additions and 617 deletions.
42 changes: 21 additions & 21 deletions accounts/account_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ and accounts persistence is derived from stored keys' addresses
package accounts

import (
"bytes"
"crypto/ecdsa"
crand "crypto/rand"
"errors"
"os"
"sync"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)

Expand All @@ -50,12 +50,12 @@ var (
)

type Account struct {
Address []byte
Address common.Address
}

type Manager struct {
keyStore crypto.KeyStore2
unlocked map[string]*unlocked
unlocked map[common.Address]*unlocked
mutex sync.RWMutex
}

Expand All @@ -67,40 +67,40 @@ type unlocked struct {
func NewManager(keyStore crypto.KeyStore2) *Manager {
return &Manager{
keyStore: keyStore,
unlocked: make(map[string]*unlocked),
unlocked: make(map[common.Address]*unlocked),
}
}

func (am *Manager) HasAccount(addr []byte) bool {
func (am *Manager) HasAccount(addr common.Address) bool {
accounts, _ := am.Accounts()
for _, acct := range accounts {
if bytes.Compare(acct.Address, addr) == 0 {
if acct.Address == addr {
return true
}
}
return false
}

func (am *Manager) Primary() (addr []byte, err error) {
func (am *Manager) Primary() (addr common.Address, err error) {
addrs, err := am.keyStore.GetKeyAddresses()
if os.IsNotExist(err) {
return nil, ErrNoKeys
return common.Address{}, ErrNoKeys
} else if err != nil {
return nil, err
return common.Address{}, err
}
if len(addrs) == 0 {
return nil, ErrNoKeys
return common.Address{}, ErrNoKeys
}
return addrs[0], nil
}

func (am *Manager) DeleteAccount(address []byte, auth string) error {
func (am *Manager) DeleteAccount(address common.Address, auth string) error {
return am.keyStore.DeleteKey(address, auth)
}

func (am *Manager) Sign(a Account, toSign []byte) (signature []byte, err error) {
am.mutex.RLock()
unlockedKey, found := am.unlocked[string(a.Address)]
unlockedKey, found := am.unlocked[a.Address]
am.mutex.RUnlock()
if !found {
return nil, ErrLocked
Expand All @@ -111,7 +111,7 @@ func (am *Manager) Sign(a Account, toSign []byte) (signature []byte, err error)

// TimedUnlock unlocks the account with the given address.
// When timeout has passed, the account will be locked again.
func (am *Manager) TimedUnlock(addr []byte, keyAuth string, timeout time.Duration) error {
func (am *Manager) TimedUnlock(addr common.Address, keyAuth string, timeout time.Duration) error {
key, err := am.keyStore.GetKey(addr, keyAuth)
if err != nil {
return err
Expand All @@ -124,7 +124,7 @@ func (am *Manager) TimedUnlock(addr []byte, keyAuth string, timeout time.Duratio
// Unlock unlocks the account with the given address. The account
// stays unlocked until the program exits or until a TimedUnlock
// timeout (started after the call to Unlock) expires.
func (am *Manager) Unlock(addr []byte, keyAuth string) error {
func (am *Manager) Unlock(addr common.Address, keyAuth string) error {
key, err := am.keyStore.GetKey(addr, keyAuth)
if err != nil {
return err
Expand Down Expand Up @@ -157,10 +157,10 @@ func (am *Manager) Accounts() ([]Account, error) {
return accounts, err
}

func (am *Manager) addUnlocked(addr []byte, key *crypto.Key) *unlocked {
func (am *Manager) addUnlocked(addr common.Address, key *crypto.Key) *unlocked {
u := &unlocked{Key: key, abort: make(chan struct{})}
am.mutex.Lock()
prev, found := am.unlocked[string(addr)]
prev, found := am.unlocked[addr]
if found {
// terminate dropLater for this key to avoid unexpected drops.
close(prev.abort)
Expand All @@ -169,12 +169,12 @@ func (am *Manager) addUnlocked(addr []byte, key *crypto.Key) *unlocked {
// key, i.e. when Unlock was used.
zeroKey(prev.PrivateKey)
}
am.unlocked[string(addr)] = u
am.unlocked[addr] = u
am.mutex.Unlock()
return u
}

func (am *Manager) dropLater(addr []byte, u *unlocked, timeout time.Duration) {
func (am *Manager) dropLater(addr common.Address, u *unlocked, timeout time.Duration) {
t := time.NewTimer(timeout)
defer t.Stop()
select {
Expand All @@ -186,9 +186,9 @@ func (am *Manager) dropLater(addr []byte, u *unlocked, timeout time.Duration) {
// was launched with. we can check that using pointer equality
// because the map stores a new pointer every time the key is
// unlocked.
if am.unlocked[string(addr)] == u {
if am.unlocked[addr] == u {
zeroKey(u.PrivateKey)
delete(am.unlocked, string(addr))
delete(am.unlocked, addr)
}
am.mutex.Unlock()
}
Expand All @@ -204,7 +204,7 @@ func zeroKey(k *ecdsa.PrivateKey) {

// 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 {
func (am *Manager) Export(path string, addr common.Address, keyAuth string) error {
key, err := am.keyStore.GetKey(addr, keyAuth)
if err != nil {
return err
Expand Down
26 changes: 17 additions & 9 deletions cmd/geth/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
// Add the accouns to a new set
accountSet := set.New()
for _, account := range accounts {
accountSet.Add(common.BytesToAddress(account.Address))
accountSet.Add(account.Address)
}

//ltxs := make([]*tx, len(txs))
Expand Down Expand Up @@ -275,14 +275,22 @@ func (js *jsre) verbosity(call otto.FunctionCall) otto.Value {
}

func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
_, err := call.Argument(0).ToInteger()
if err != nil {
fmt.Println(err)
return otto.FalseValue()
var (
threads int64
err error
)

if len(call.ArgumentList) > 0 {
threads, err = call.Argument(0).ToInteger()
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
} else {
threads = 4
}
// threads now ignored

err = js.ethereum.StartMining()
err = js.ethereum.StartMining(int(threads))
if err != nil {
fmt.Println(err)
return otto.FalseValue()
Expand Down Expand Up @@ -383,7 +391,7 @@ func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
}
}
am := js.ethereum.AccountManager()
err = am.TimedUnlock(common.FromHex(addr), passphrase, time.Duration(seconds)*time.Second)
err = am.TimedUnlock(common.HexToAddress(addr), passphrase, time.Duration(seconds)*time.Second)
if err != nil {
fmt.Printf("Unlock account failed '%v'\n", err)
return otto.FalseValue()
Expand Down Expand Up @@ -425,7 +433,7 @@ func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
fmt.Printf("Could not create the account: %v", err)
return otto.UndefinedValue()
}
return js.re.ToVal(common.ToHex(acct.Address))
return js.re.ToVal(acct.Address.Hex())
}

func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/info_test.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"code":"605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056","info":{"abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"compilerVersion":"0.9.13","developerDoc":{"methods":{}},"language":"Solidity","languageVersion":"0","source":"contract test {\n /// @notice Will multiply `a` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply `a` by 7."}}}}}
{"code":"605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056","info":{"abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"compilerVersion":"0.9.17","developerDoc":{"methods":{}},"language":"Solidity","languageVersion":"0","source":"contract test {\n /// @notice Will multiply `a` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply `a` by 7."}}}}}
7 changes: 4 additions & 3 deletions cmd/geth/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ import (
"fmt"
"math/big"
"os"
"path"
"path/filepath"
"strings"

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/docserver"
"github.com/ethereum/go-ethereum/common/natspec"
"github.com/ethereum/go-ethereum/eth"
Expand Down Expand Up @@ -164,7 +165,7 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
return false
}
// TODO: allow retry
if err := self.ethereum.AccountManager().Unlock(addr, pass); err != nil {
if err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(addr), pass); err != nil {
return false
} else {
fmt.Println("Account is now unlocked for this session.")
Expand Down Expand Up @@ -209,7 +210,7 @@ func (self *jsre) interactive() {
}

func (self *jsre) withHistory(op func(*os.File)) {
hist, err := os.OpenFile(path.Join(self.ethereum.DataDir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
hist, err := os.OpenFile(filepath.Join(self.ethereum.DataDir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
fmt.Printf("unable to open history file: %v\n", err)
return
Expand Down
51 changes: 44 additions & 7 deletions cmd/geth/js_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
Expand All @@ -25,10 +24,13 @@ import (

const (
testSolcPath = ""
solcVersion = "0.9.17"

testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
testBalance = "10000000000000000000"
// of empty string
testHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)

var (
Expand All @@ -43,7 +45,7 @@ type testjethre struct {
}

func (self *testjethre) UnlockAccount(acc []byte) bool {
err := self.ethereum.AccountManager().Unlock(acc, "")
err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "")
if err != nil {
panic("unable to unlock")
}
Expand All @@ -66,7 +68,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
// set up mock genesis with balance on the testAddress
core.GenesisData = []byte(testGenesis)

ks := crypto.NewKeyStorePassphrase(filepath.Join(tmp, "keys"))
ks := crypto.NewKeyStorePassphrase(filepath.Join(tmp, "keystore"))
am := accounts.NewManager(ks)
ethereum, err := eth.New(&eth.Config{
DataDir: tmp,
Expand All @@ -93,7 +95,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
t.Fatal(err)
}

assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
ds, err := docserver.New("/")
if err != nil {
t.Errorf("Error creating DocServer: %v", err)
Expand Down Expand Up @@ -215,7 +217,34 @@ func TestCheckTestAccountBalance(t *testing.T) {
checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"`+testBalance+`"`)
}

func TestSignature(t *testing.T) {
tmp, repl, ethereum := testJEthRE(t)
if err := ethereum.Start(); err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
defer ethereum.Stop()
defer os.RemoveAll(tmp)

val, err := repl.re.Run(`eth.sign({from: "` + testAddress + `", data: "` + testHash + `"})`)

// This is a very preliminary test, lacking actual signature verification
if err != nil {
t.Errorf("Error runnig js: %v", err)
return
}
output := val.String()
t.Logf("Output: %v", output)

regex := regexp.MustCompile(`^0x[0-9a-f]{130}$`)
if !regex.MatchString(output) {
t.Errorf("Signature is not 65 bytes represented in hexadecimal.")
return
}
}

func TestContract(t *testing.T) {
t.Skip()

tmp, repl, ethereum := testJEthRE(t)
if err := ethereum.Start(); err != nil {
Expand Down Expand Up @@ -245,9 +274,16 @@ func TestContract(t *testing.T) {
checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`)
checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`)

_, err = compiler.New("")
// if solc is found with right version, test it, otherwise read from file
sol, err := compiler.New("")
if err != nil {
t.Logf("solc not found: skipping compiler test")
} else if sol.Version() != solcVersion {
err = fmt.Errorf("solc wrong version found (%v, expect %v): skipping compiler test", sol.Version(), solcVersion)
t.Log(err)
}

if err != nil {
info, err := ioutil.ReadFile("info_test.json")
if err != nil {
t.Fatalf("%v", err)
Expand All @@ -259,6 +295,7 @@ func TestContract(t *testing.T) {
} else {
checkEvalJSON(t, repl, `contract = eth.compile.solidity(source)`, string(contractInfo))
}

checkEvalJSON(t, repl, `contract.code`, `"605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056"`)

checkEvalJSON(
Expand Down Expand Up @@ -298,7 +335,7 @@ multiply7 = new Multiply7(contractaddress);
}

checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`)
checkEvalJSON(t, repl, `contenthash = admin.contractInfo.register(primary, contractaddress, contract, filename)`, `"0x57e577316ccee6514797d9de9823af2004fdfe22bcfb6e39bbb8f92f57dcc421"`)
checkEvalJSON(t, repl, `contenthash = admin.contractInfo.register(primary, contractaddress, contract, filename)`, `"0x0d067e2dd99a4d8f0c0279738b17130dd415a89f24a23f0e7cf68c546ae3089d"`)
checkEvalJSON(t, repl, `admin.contractInfo.registerUrl(primary, contenthash, "file://"+filename)`, `true`)
if err != nil {
t.Errorf("unexpected error registering, got %v", err)
Expand All @@ -324,7 +361,7 @@ func checkEvalJSON(t *testing.T, re *testjethre, expr, want string) error {
}
if err != nil {
_, file, line, _ := runtime.Caller(1)
file = path.Base(file)
file = filepath.Base(file)
fmt.Printf("\t%s:%d: %v\n", file, line, err)
t.Fail()
}
Expand Down

0 comments on commit 8e24378

Please sign in to comment.