diff options
author | Jeffrey Wilcke <jeffrey@ethereum.org> | 2016-01-21 05:17:46 +0800 |
---|---|---|
committer | Jeffrey Wilcke <jeffrey@ethereum.org> | 2016-01-21 05:17:46 +0800 |
commit | 7b11e9444195cc728437d568bb61e1e86034ba39 (patch) | |
tree | 05df00d45c9066c1eb29e3c8f55ddb8b5048376a | |
parent | e7f6798b591d08e1a3b6d23eda46519e2564f6e6 (diff) | |
parent | cdd34fcb166cdb90ee411d029e6851325e80c8d3 (diff) | |
download | go-tangerine-7b11e9444195cc728437d568bb61e1e86034ba39.tar.gz go-tangerine-7b11e9444195cc728437d568bb61e1e86034ba39.tar.zst go-tangerine-7b11e9444195cc728437d568bb61e1e86034ba39.zip |
Merge pull request #2132 from bas-vk/console-sleep
console: add admin.sleep and admin.sleepBlocks
-rw-r--r-- | cmd/geth/js.go | 9 | ||||
-rw-r--r-- | rpc/jeth.go | 75 |
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() +} |