diff options
-rw-r--r-- | accounts/accounts_test.go | 3 | ||||
-rw-r--r-- | cmd/ethereum/flags.go | 11 | ||||
-rw-r--r-- | cmd/mist/assets/examples/coin.html | 24 | ||||
-rw-r--r-- | cmd/mist/flags.go | 10 | ||||
-rw-r--r-- | core/chain_manager.go | 31 | ||||
-rw-r--r-- | crypto/key_store_plain.go | 7 | ||||
-rw-r--r-- | crypto/key_store_test.go | 9 | ||||
-rw-r--r-- | ethutil/common.go | 12 | ||||
-rw-r--r-- | event/filter/eth_filter.go | 3 | ||||
-rw-r--r-- | rpc/args.go | 7 | ||||
-rw-r--r-- | rpc/packages.go | 23 | ||||
-rw-r--r-- | rpc/packages_test.go | 1 | ||||
-rw-r--r-- | rpc/util.go | 4 | ||||
-rw-r--r-- | whisper/whisper.go | 4 | ||||
-rw-r--r-- | xeth/xeth.go | 10 |
15 files changed, 90 insertions, 69 deletions
diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index 30e8c6285..127334404 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -5,10 +5,11 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/randentropy" + "github.com/ethereum/go-ethereum/ethutil" ) func TestAccountManager(t *testing.T) { - ks := crypto.NewKeyStorePlain(crypto.DefaultDataDir()) + ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir()) am := NewAccountManager(ks) pass := "" // not used but required by API a1, err := am.NewAccount(pass) diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go index 577bee442..7d410c8e4 100644 --- a/cmd/ethereum/flags.go +++ b/cmd/ethereum/flags.go @@ -26,10 +26,10 @@ import ( "fmt" "log" "os" - "os/user" "path" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/vm" @@ -79,12 +79,7 @@ var ( InputFile string ) -func defaultDataDir() string { - usr, _ := user.Current() - return path.Join(usr.HomeDir, ".ethereum") -} - -var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini") +var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini") func Init() { // TODO: move common flag processing to cmd/util @@ -107,7 +102,7 @@ func Init() { flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") - flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") + flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html index 18a6811d7..509a9aeeb 100644 --- a/cmd/mist/assets/examples/coin.html +++ b/cmd/mist/assets/examples/coin.html @@ -19,6 +19,7 @@ <span>Amount:</span> <input type="text" id="amount" style="width:200px"> <button onclick="transact()">Send</button> + <span id="message"></span> </div> <hr> @@ -95,17 +96,28 @@ } function transact() { - var to = document.querySelector("#address").value; - if( to.length == 0 ) { + var to = document.querySelector("#address"); + if( to.value.length == 0 ) { to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3"; } else { - to = "0x"+to; + if (to.value.substr(0,2) != "0x") + to.value = "0x"+to.value; } - var value = parseInt( document.querySelector("#amount").value ); - console.log("transact: ", to, " => ", value) + var value = document.querySelector("#amount"); + var amount = parseInt( value.value ); + console.log("transact: ", to.value, " => ", amount) - contract.send( to, value ); + contract.send( to.value, amount ); + + to.value = ""; + value.value = ""; + + var message = document.querySelector("#message") + message.innerHTML = "Submitted"; + setTimeout(function() { + message.innerHTML = ""; + }, 1000); } refresh(); diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go index d9487de9e..d5ed60a21 100644 --- a/cmd/mist/flags.go +++ b/cmd/mist/flags.go @@ -26,13 +26,13 @@ import ( "fmt" "log" "os" - "os/user" "path" "path/filepath" "runtime" "bitbucket.org/kardianos/osext" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/vm" @@ -94,12 +94,8 @@ func defaultAssetPath() string { } return assetPath } -func defaultDataDir() string { - usr, _ := user.Current() - return path.Join(usr.HomeDir, ".ethereum") -} -var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini") +var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini") func Init() { // TODO: move common flag processing to cmd/utils @@ -121,7 +117,7 @@ func Init() { flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") - flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") + flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") diff --git a/core/chain_manager.go b/core/chain_manager.go index 9ef091c3c..959bfd398 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -85,12 +85,14 @@ type ChainManager struct { lastBlockHash []byte transState *state.StateDB + txState *state.StateDB } func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager { bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux} bc.setLastBlock() bc.transState = bc.State().Copy() + bc.txState = bc.State().Copy() return bc } @@ -138,6 +140,19 @@ func (self *ChainManager) TransState() *state.StateDB { return self.transState } +func (self *ChainManager) TxState() *state.StateDB { + self.tsmu.RLock() + defer self.tsmu.RUnlock() + + return self.txState +} + +func (self *ChainManager) setTxState(state *state.StateDB) { + self.tsmu.Lock() + defer self.tsmu.Unlock() + self.txState = state +} + func (self *ChainManager) setTransState(statedb *state.StateDB) { self.transState = statedb } @@ -268,7 +283,6 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain break } } - fmt.Printf("get hash %x (%d)\n", hash, len(chain)) return } @@ -363,6 +377,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { defer self.tsmu.Unlock() for _, block := range chain { + // Call in to the block processor and check for errors. It's likely that if one block fails + // all others will fail too (unless a known block is returned). td, err := self.processor.Process(block) if err != nil { if IsKnownBlockErr(err) { @@ -377,11 +393,15 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { } block.Td = td - var chain, split bool + var canonical, split bool self.mu.Lock() { + // Write block to database. Eventually we'll have to improve on this and throw away blocks that are + // not in the canonical chain. self.write(block) cblock := self.currentBlock + // Compare the TD of the last known block in the canonical chain to make sure it's greater. + // At this point it's possible that a different chain (fork) becomes the new canonical chain. if td.Cmp(self.td) > 0 { if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 { chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td) @@ -391,17 +411,18 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.setTotalDifficulty(td) self.insert(block) - chain = true + canonical = true } } self.mu.Unlock() - if chain { + if canonical { + self.setTransState(state.New(block.Root(), self.db)) self.eventMux.Post(ChainEvent{block, td}) } if split { - self.setTransState(state.New(block.Root(), self.db)) + self.setTxState(state.New(block.Root(), self.db)) self.eventMux.Post(ChainSplitEvent{block}) } } diff --git a/crypto/key_store_plain.go b/crypto/key_store_plain.go index 6b76962a0..255ae0ed7 100644 --- a/crypto/key_store_plain.go +++ b/crypto/key_store_plain.go @@ -30,7 +30,6 @@ import ( "io" "io/ioutil" "os" - "os/user" "path" ) @@ -48,12 +47,6 @@ type keyStorePlain struct { keysDirPath string } -// TODO: copied from cmd/ethereum/flags.go -func DefaultDataDir() string { - usr, _ := user.Current() - return path.Join(usr.HomeDir, ".ethereum") -} - func NewKeyStorePlain(path string) KeyStore2 { return &keyStorePlain{path} } diff --git a/crypto/key_store_test.go b/crypto/key_store_test.go index 485d8f536..11531d460 100644 --- a/crypto/key_store_test.go +++ b/crypto/key_store_test.go @@ -2,12 +2,13 @@ package crypto import ( "github.com/ethereum/go-ethereum/crypto/randentropy" + "github.com/ethereum/go-ethereum/ethutil" "reflect" "testing" ) func TestKeyStorePlain(t *testing.T) { - ks := NewKeyStorePlain(DefaultDataDir()) + ks := NewKeyStorePlain(ethutil.DefaultDataDir()) pass := "" // not used but required by API k1, err := ks.GenerateNewKey(randentropy.Reader, pass) if err != nil { @@ -35,7 +36,7 @@ func TestKeyStorePlain(t *testing.T) { } func TestKeyStorePassphrase(t *testing.T) { - ks := NewKeyStorePassphrase(DefaultDataDir()) + ks := NewKeyStorePassphrase(ethutil.DefaultDataDir()) pass := "foo" k1, err := ks.GenerateNewKey(randentropy.Reader, pass) if err != nil { @@ -61,7 +62,7 @@ func TestKeyStorePassphrase(t *testing.T) { } func TestKeyStorePassphraseDecryptionFail(t *testing.T) { - ks := NewKeyStorePassphrase(DefaultDataDir()) + ks := NewKeyStorePassphrase(ethutil.DefaultDataDir()) pass := "foo" k1, err := ks.GenerateNewKey(randentropy.Reader, pass) if err != nil { @@ -89,7 +90,7 @@ func TestImportPreSaleKey(t *testing.T) { // python pyethsaletool.py genwallet // with password "foo" fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" - ks := NewKeyStorePassphrase(DefaultDataDir()) + ks := NewKeyStorePassphrase(ethutil.DefaultDataDir()) pass := "foo" _, err := ImportPreSaleKey(ks, []byte(fileContent), pass) if err != nil { diff --git a/ethutil/common.go b/ethutil/common.go index 2ef2440c7..efc519732 100644 --- a/ethutil/common.go +++ b/ethutil/common.go @@ -3,10 +3,22 @@ package ethutil import ( "fmt" "math/big" + "os/user" + "path" "runtime" "time" ) +func DefaultDataDir() string { + usr, _ := user.Current() + if runtime.GOOS == "darwin" { + return path.Join(usr.HomeDir, "Library/Ethereum") + } else if runtime.GOOS == "windows" { + return path.Join(usr.HomeDir, "AppData/Roaming/Ethereum") + } else { + return path.Join(usr.HomeDir, ".ethereum") + } +} func IsWindows() bool { return runtime.GOOS == "windows" } diff --git a/event/filter/eth_filter.go b/event/filter/eth_filter.go index 73d2cd935..4ba66a7e0 100644 --- a/event/filter/eth_filter.go +++ b/event/filter/eth_filter.go @@ -3,7 +3,6 @@ package filter // TODO make use of the generic filtering system import ( - "fmt" "sync" "github.com/ethereum/go-ethereum/core" @@ -75,7 +74,6 @@ out: case event := <-events.Chan(): switch event := event.(type) { case core.ChainEvent: - fmt.Println("filter start") self.filterMu.RLock() for _, filter := range self.filters { if filter.BlockCallback != nil { @@ -83,7 +81,6 @@ out: } } self.filterMu.RUnlock() - fmt.Println("filter stop") case core.PendingBlockEvent: self.filterMu.RLock() diff --git a/rpc/args.go b/rpc/args.go index f730819fd..347f60410 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -22,13 +22,6 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) { return NewErrorResponse(ErrorDecodeArgs) } -func (obj *GetBlockArgs) requirements() error { - if obj.BlockNumber == 0 && obj.Hash == "" { - return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument") - } - return nil -} - type NewTxArgs struct { From string `json:"from"` To string `json:"to"` diff --git a/rpc/packages.go b/rpc/packages.go index bf75d1ddb..0f00441d2 100644 --- a/rpc/packages.go +++ b/rpc/packages.go @@ -126,10 +126,6 @@ func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error self.logMut.Lock() defer self.logMut.Unlock() - if self.logs[id] == nil { - self.logs[id] = &logFilter{timeout: time.Now()} - } - self.logs[id].add(&state.StateLog{}) } if args == "pending" { @@ -139,6 +135,7 @@ func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error } id = self.filterManager.InstallFilter(filter) + self.logs[id] = &logFilter{timeout: time.Now()} *reply = id return nil @@ -177,15 +174,11 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error } func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error { - err := args.requirements() - if err != nil { - return err - } - - if args.BlockNumber > 0 { - *reply = p.xeth.BlockByNumber(args.BlockNumber) - } else { + // This seems a bit precarious Maybe worth splitting to discrete functions + if len(args.Hash) > 0 { *reply = p.xeth.BlockByHash(args.Hash) + } else { + *reply = p.xeth.BlockByNumber(args.BlockNumber) } return nil } @@ -377,12 +370,10 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e args.Fn = func(msg xeth.WhisperMessage) { p.messagesMut.Lock() defer p.messagesMut.Unlock() - if p.messages[id] == nil { - p.messages[id] = &whisperFilter{timeout: time.Now()} - } p.messages[id].add(msg) // = append(p.messages[id], msg) } id = p.xeth.Whisper().Watch(args) + p.messages[id] = &whisperFilter{timeout: time.Now()} *reply = id return nil } @@ -623,12 +614,14 @@ done: self.messagesMut.Lock() for id, filter := range self.logs { if time.Since(filter.timeout) > 20*time.Second { + self.filterManager.UninstallFilter(id) delete(self.logs, id) } } for id, filter := range self.messages { if time.Since(filter.timeout) > 20*time.Second { + self.xeth.Whisper().Unwatch(id) delete(self.messages, id) } } diff --git a/rpc/packages_test.go b/rpc/packages_test.go index 037fd78b3..a9fc16cd3 100644 --- a/rpc/packages_test.go +++ b/rpc/packages_test.go @@ -7,6 +7,7 @@ import ( ) func TestFilterClose(t *testing.T) { + t.Skip() api := &EthereumApi{ logs: make(map[int]*logFilter), messages: make(map[int]*whisperFilter), diff --git a/rpc/util.go b/rpc/util.go index 1939b3474..3e8ca3fef 100644 --- a/rpc/util.go +++ b/rpc/util.go @@ -82,7 +82,7 @@ type RpcServer interface { type Log struct { Address string `json:"address"` - Topic []string `json:"topics"` + Topic []string `json:"topic"` Data string `json:"data"` Number uint64 `json:"number"` } @@ -108,6 +108,7 @@ func toLogs(logs state.Logs) (ls []Log) { type whisperFilter struct { messages []xeth.WhisperMessage timeout time.Time + id int } func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) { @@ -123,6 +124,7 @@ func (w *whisperFilter) get() []xeth.WhisperMessage { type logFilter struct { logs state.Logs timeout time.Time + id int } func (l *logFilter) add(logs ...state.Log) { diff --git a/whisper/whisper.go b/whisper/whisper.go index 50c2f98fd..13209f9a6 100644 --- a/whisper/whisper.go +++ b/whisper/whisper.go @@ -127,6 +127,10 @@ func (self *Whisper) Watch(opts Filter) int { }) } +func (self *Whisper) Unwatch(id int) { + self.filters.Uninstall(id) +} + func (self *Whisper) Messages(id int) (messages []*Message) { filter := self.filters.Get(id) if filter != nil { diff --git a/xeth/xeth.go b/xeth/xeth.go index 5907a8329..2985ce982 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -277,7 +277,7 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) } var err error - state := self.eth.ChainManager().TransState() + state := self.eth.ChainManager().TxState() if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 { return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value()) } @@ -289,10 +289,10 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) //fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce()) // Do some pre processing for our "pre" events and hooks - block := self.chainManager.NewBlock(key.Address()) - coinbase := state.GetOrNewStateObject(key.Address()) - coinbase.SetGasPool(block.GasLimit()) - self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true) + //block := self.chainManager.NewBlock(key.Address()) + //coinbase := state.GetOrNewStateObject(key.Address()) + //coinbase.SetGasPool(block.GasLimit()) + //self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true) err = self.eth.TxPool().Add(tx) if err != nil { |