diff options
-rw-r--r-- | cmd/geth/js.go | 9 | ||||
-rw-r--r-- | core/state/statedb.go | 3 | ||||
-rw-r--r-- | eth/handler.go | 12 | ||||
-rw-r--r-- | rpc/jeth.go | 75 |
4 files changed, 92 insertions, 7 deletions
diff --git a/cmd/geth/js.go b/cmd/geth/js.go index 9329eaa0e..cdafab7fa 100644 --- a/cmd/geth/js.go +++ b/cmd/geth/js.go @@ -348,6 +348,15 @@ func (js *jsre) apiBindings(f xeth.Frontend) error { persObj.Set("newAccount", jeth.NewAccount) } + // The admin.sleep and admin.sleepBlocks are offered by the console and not by the RPC layer. + // Bind these if the admin module is available. + if a, err := js.re.Get("admin"); err == nil { + if adminObj := a.Object(); adminObj != nil { + adminObj.Set("sleepBlocks", jeth.SleepBlocks) + adminObj.Set("sleep", jeth.Sleep) + } + } + return nil } diff --git a/core/state/statedb.go b/core/state/statedb.go index 413321057..8093472b5 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -353,7 +353,8 @@ func (s *StateDB) IntermediateRoot() common.Hash { // Commit commits all state changes to the database. func (s *StateDB) Commit() (root common.Hash, err error) { - return s.commit(s.db) + root, batch := s.CommitBatch() + return root, batch.Write() } // CommitBatch commits all state changes to a write batch but does not diff --git a/eth/handler.go b/eth/handler.go index 108a6679c..e8bac23c3 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -750,10 +750,10 @@ func (self *ProtocolManager) txBroadcastLoop() { // EthNodeInfo represents a short summary of the Ethereum sub-protocol metadata known // about the host peer. type EthNodeInfo struct { - Network int `json:"network"` // Ethereum network ID (0=Olympic, 1=Frontier, 2=Morden) - Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain - Genesis string `json:"genesis"` // SHA3 hash of the host's genesis block - Head string `json:"head"` // SHA3 hash of the host's best owned block + Network int `json:"network"` // Ethereum network ID (0=Olympic, 1=Frontier, 2=Morden) + Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain + Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block + Head common.Hash `json:"head"` // SHA3 hash of the host's best owned block } // NodeInfo retrieves some protocol metadata about the running host node. @@ -761,7 +761,7 @@ func (self *ProtocolManager) NodeInfo() *EthNodeInfo { return &EthNodeInfo{ Network: self.networkId, Difficulty: self.blockchain.GetTd(self.blockchain.CurrentBlock().Hash()), - Genesis: fmt.Sprintf("%x", self.blockchain.Genesis().Hash()), - Head: fmt.Sprintf("%x", self.blockchain.CurrentBlock().Hash()), + Genesis: self.blockchain.Genesis().Hash(), + Head: self.blockchain.CurrentBlock().Hash(), } } diff --git a/rpc/jeth.go b/rpc/jeth.go index de7dd1e76..b195a4965 100644 --- a/rpc/jeth.go +++ b/rpc/jeth.go @@ -19,6 +19,7 @@ package rpc import ( "encoding/json" "fmt" + "time" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/jsre" @@ -247,3 +248,77 @@ func (self *Jeth) confirmTransaction(id interface{}, jsonrpc string, args []inte // Accept all tx which are send from this console return self.client.Send(shared.NewRpcResponse(id, jsonrpc, true, nil)) == nil } + +// throwJSExeception panics on an otto value, the Otto VM will then throw msg as a javascript error. +func throwJSExeception(msg interface{}) otto.Value { + p, _ := otto.ToValue(msg) + panic(p) + return p +} + +// Sleep will halt the console for arg[0] seconds. +func (self *Jeth) Sleep(call otto.FunctionCall) (response otto.Value) { + if len(call.ArgumentList) >= 1 { + if call.Argument(0).IsNumber() { + sleep, _ := call.Argument(0).ToInteger() + time.Sleep(time.Duration(sleep) * time.Second) + return otto.TrueValue() + } + } + return throwJSExeception("usage: sleep(<sleep in seconds>)") +} + +// SleepBlocks will wait for a specified number of new blocks or max for a +// given of seconds. sleepBlocks(nBlocks[, maxSleep]). +func (self *Jeth) SleepBlocks(call otto.FunctionCall) (response otto.Value) { + nBlocks := int64(0) + maxSleep := int64(9999999999999999) // indefinitely + + nArgs := len(call.ArgumentList) + + if nArgs == 0 { + throwJSExeception("usage: sleepBlocks(<n blocks>[, max sleep in seconds])") + } + + if nArgs >= 1 { + if call.Argument(0).IsNumber() { + nBlocks, _ = call.Argument(0).ToInteger() + } else { + throwJSExeception("expected number as first argument") + } + } + + if nArgs >= 2 { + if call.Argument(1).IsNumber() { + maxSleep, _ = call.Argument(1).ToInteger() + } else { + throwJSExeception("expected number as second argument") + } + } + + // go through the console, this will allow web3 to call the appropriate + // callbacks if a delayed response or notification is received. + currentBlockNr := func() int64 { + result, err := call.Otto.Run("eth.blockNumber") + if err != nil { + throwJSExeception(err.Error()) + } + blockNr, err := result.ToInteger() + if err != nil { + throwJSExeception(err.Error()) + } + return blockNr + } + + targetBlockNr := currentBlockNr() + nBlocks + deadline := time.Now().Add(time.Duration(maxSleep) * time.Second) + + for time.Now().Before(deadline) { + if currentBlockNr() >= targetBlockNr { + return otto.TrueValue() + } + time.Sleep(time.Second) + } + + return otto.FalseValue() +} |