aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/js.go9
-rw-r--r--core/chain_makers.go19
-rw-r--r--core/state/statedb.go3
-rw-r--r--core/vm/contract.go7
-rw-r--r--core/vm/environment.go1
-rw-r--r--core/vm/jit_test.go17
-rw-r--r--core/vm/vm.go9
-rw-r--r--docker/Dockerfile21
-rw-r--r--docker/develop/Dockerfile17
-rw-r--r--docker/master/Dockerfile17
-rw-r--r--eth/handler.go12
-rw-r--r--rpc/jeth.go75
12 files changed, 153 insertions, 54 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/chain_makers.go b/core/chain_makers.go
index 5a8f380a3..c62618e6c 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -91,15 +91,10 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
- _, gas, err := ApplyMessage(NewEnv(b.statedb, nil, tx, b.header), tx, b.gasPool)
+ receipt, _, _, err := ApplyTransaction(nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed)
if err != nil {
panic(err)
}
- root := b.statedb.IntermediateRoot()
- b.header.GasUsed.Add(b.header.GasUsed, gas)
- receipt := types.NewReceipt(root.Bytes(), b.header.GasUsed)
- receipt.Logs = b.statedb.GetLogs(tx.Hash())
- receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt)
}
@@ -169,12 +164,8 @@ func (b *BlockGen) OffsetTime(seconds int64) {
// values. Inserting them into BlockChain requires use of FakePow or
// a similar non-validating proof of work implementation.
func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
- statedb, err := state.New(parent.Root(), db)
- if err != nil {
- panic(err)
- }
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
- genblock := func(i int, h *types.Header) (*types.Block, types.Receipts) {
+ genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb}
if gen != nil {
gen(i, b)
@@ -188,8 +179,12 @@ func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int,
return types.NewBlock(h, b.txs, b.uncles, b.receipts), b.receipts
}
for i := 0; i < n; i++ {
+ statedb, err := state.New(parent.Root(), db)
+ if err != nil {
+ panic(err)
+ }
header := makeHeader(parent, statedb)
- block, receipt := genblock(i, header)
+ block, receipt := genblock(i, header, statedb)
blocks[i] = block
receipts[i] = receipt
parent = block
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/core/vm/contract.go b/core/vm/contract.go
index 95417e747..5981dcca0 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -27,6 +27,7 @@ type ContractRef interface {
ReturnGas(*big.Int, *big.Int)
Address() common.Address
SetCode([]byte)
+ EachStorage(cb func(key, value []byte))
}
// Contract represents an ethereum contract in the state database. It contains
@@ -124,3 +125,9 @@ func (self *Contract) SetCallCode(addr *common.Address, code []byte) {
self.Code = code
self.CodeAddr = addr
}
+
+// EachStorage iterates the contract's storage and calls a method for every key
+// value pair.
+func (self *Contract) EachStorage(cb func(key, value []byte)) {
+ self.caller.EachStorage(cb)
+}
diff --git a/core/vm/environment.go b/core/vm/environment.go
index 299d12674..4fee583bf 100644
--- a/core/vm/environment.go
+++ b/core/vm/environment.go
@@ -121,4 +121,5 @@ type Account interface {
Address() common.Address
ReturnGas(*big.Int, *big.Int)
SetCode([]byte)
+ EachStorage(cb func(key, value []byte))
}
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index aa97e5184..8c50ed0f5 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -125,14 +125,15 @@ type vmBench struct {
type account struct{}
-func (account) SubBalance(amount *big.Int) {}
-func (account) AddBalance(amount *big.Int) {}
-func (account) SetBalance(*big.Int) {}
-func (account) SetNonce(uint64) {}
-func (account) Balance() *big.Int { return nil }
-func (account) Address() common.Address { return common.Address{} }
-func (account) ReturnGas(*big.Int, *big.Int) {}
-func (account) SetCode([]byte) {}
+func (account) SubBalance(amount *big.Int) {}
+func (account) AddBalance(amount *big.Int) {}
+func (account) SetBalance(*big.Int) {}
+func (account) SetNonce(uint64) {}
+func (account) Balance() *big.Int { return nil }
+func (account) Address() common.Address { return common.Address{} }
+func (account) ReturnGas(*big.Int, *big.Int) {}
+func (account) SetCode([]byte) {}
+func (account) EachStorage(cb func(key, value []byte)) {}
func runVmBench(test vmBench, b *testing.B) {
var sender account
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 4b03e55f0..8e07aaa89 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -376,12 +376,9 @@ func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, st
stck[i] = new(big.Int).Set(item)
}
storage := make(map[common.Hash][]byte)
- /*
- object := contract.self.(*state.StateObject)
- object.EachStorage(func(k, v []byte) {
- storage[common.BytesToHash(k)] = v
- })
- */
+ contract.self.EachStorage(func(k, v []byte) {
+ storage[common.BytesToHash(k)] = v
+ })
self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, err})
}
}
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index ba5b05d14..000000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,21 +0,0 @@
-FROM ubuntu:wily
-MAINTAINER caktux
-
-ENV DEBIAN_FRONTEND noninteractive
-
-# Usual update / upgrade
-RUN apt-get update
-RUN apt-get upgrade -q -y
-RUN apt-get dist-upgrade -q -y
-
-# Install Ethereum
-RUN apt-get install -q -y software-properties-common
-RUN add-apt-repository ppa:ethereum/ethereum
-RUN add-apt-repository ppa:ethereum/ethereum-dev
-RUN apt-get update
-RUN apt-get install -q -y geth
-
-EXPOSE 8545
-EXPOSE 30303
-
-ENTRYPOINT ["/usr/bin/geth"]
diff --git a/docker/develop/Dockerfile b/docker/develop/Dockerfile
new file mode 100644
index 000000000..98b4aadf8
--- /dev/null
+++ b/docker/develop/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:wily
+MAINTAINER caktux
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && \
+ apt-get upgrade -q -y && \
+ apt-get dist-upgrade -q -y && \
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 923F6CA9 && \
+ echo "deb http://ppa.launchpad.net/ethereum/ethereum-dev/ubuntu wily main" | tee -a /etc/apt/sources.list.d/ethereum.list && \
+ apt-get update && \
+ apt-get install -q -y geth
+
+EXPOSE 8545
+EXPOSE 30303
+
+ENTRYPOINT ["/usr/bin/geth"]
diff --git a/docker/master/Dockerfile b/docker/master/Dockerfile
new file mode 100644
index 000000000..2c6de28c9
--- /dev/null
+++ b/docker/master/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:wily
+MAINTAINER caktux
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && \
+ apt-get upgrade -q -y && \
+ apt-get dist-upgrade -q -y && \
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 923F6CA9 && \
+ echo "deb http://ppa.launchpad.net/ethereum/ethereum/ubuntu wily main" | tee -a /etc/apt/sources.list.d/ethereum.list && \
+ apt-get update && \
+ apt-get install -q -y geth
+
+EXPOSE 8545
+EXPOSE 30303
+
+ENTRYPOINT ["/usr/bin/geth"]
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()
+}