aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBas van Kervel <bas@ethdev.com>2016-01-19 16:26:17 +0800
committerBas van Kervel <bas@ethdev.com>2016-01-19 19:30:33 +0800
commitcdd34fcb166cdb90ee411d029e6851325e80c8d3 (patch)
tree53f5405ffae92580446e8a6790b1c39b5084b9e0
parent5945a33350ea6e8bfc6308826efe16aab0e2e93d (diff)
downloaddexon-cdd34fcb166cdb90ee411d029e6851325e80c8d3.tar.gz
dexon-cdd34fcb166cdb90ee411d029e6851325e80c8d3.tar.zst
dexon-cdd34fcb166cdb90ee411d029e6851325e80c8d3.zip
console: add admin.sleep and admin.sleepBlocks
-rw-r--r--cmd/geth/js.go9
-rw-r--r--rpc/jeth.go75
2 files changed, 84 insertions, 0 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/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()
+}