aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/js.go2
-rw-r--r--core/state/state_object.go1
-rw-r--r--core/state/state_test.go104
-rw-r--r--miner/agent.go10
-rw-r--r--rpc/comms/http.go4
5 files changed, 117 insertions, 4 deletions
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index c31deefdd..3e3600705 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -121,7 +121,7 @@ func keywordCompleter(line string) []string {
}
func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) {
- if len(line) == 0 {
+ if len(line) == 0 || pos == 0 {
return "", nil, ""
}
diff --git a/core/state/state_object.go b/core/state/state_object.go
index c76feb774..0af0fbd5a 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -263,6 +263,7 @@ func (self *StateObject) Copy() *StateObject {
stateObject.gasPool.Set(self.gasPool)
stateObject.remove = self.remove
stateObject.dirty = self.dirty
+ stateObject.deleted = self.deleted
return stateObject
}
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 5972d266a..60836738e 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -17,6 +17,7 @@
package state
import (
+ "bytes"
"math/big"
"testing"
@@ -117,3 +118,106 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {
c.Assert(data1, checker.DeepEquals, res)
}
+
+// use testing instead of checker because checker does not support
+// printing/logging in tests (-check.vv does not work)
+func TestSnapshot2(t *testing.T) {
+ db, _ := ethdb.NewMemDatabase()
+ state := New(common.Hash{}, db)
+
+ stateobjaddr0 := toAddr([]byte("so0"))
+ stateobjaddr1 := toAddr([]byte("so1"))
+ var storageaddr common.Hash
+
+ data0 := common.BytesToHash([]byte{17})
+ data1 := common.BytesToHash([]byte{18})
+
+ state.SetState(stateobjaddr0, storageaddr, data0)
+ state.SetState(stateobjaddr1, storageaddr, data1)
+
+ // db, trie are already non-empty values
+ so0 := state.GetStateObject(stateobjaddr0)
+ so0.balance = big.NewInt(42)
+ so0.nonce = 43
+ so0.gasPool = big.NewInt(44)
+ so0.code = []byte{'c', 'a', 'f', 'e'}
+ so0.codeHash = so0.CodeHash()
+ so0.remove = true
+ so0.deleted = false
+ so0.dirty = false
+ state.SetStateObject(so0)
+
+ // and one with deleted == true
+ so1 := state.GetStateObject(stateobjaddr1)
+ so1.balance = big.NewInt(52)
+ so1.nonce = 53
+ so1.gasPool = big.NewInt(54)
+ so1.code = []byte{'c', 'a', 'f', 'e', '2'}
+ so1.codeHash = so1.CodeHash()
+ so1.remove = true
+ so1.deleted = true
+ so1.dirty = true
+ state.SetStateObject(so1)
+
+ so1 = state.GetStateObject(stateobjaddr1)
+ if so1 != nil {
+ t.Fatalf("deleted object not nil when getting")
+ }
+
+ snapshot := state.Copy()
+ state.Set(snapshot)
+
+ so0Restored := state.GetStateObject(stateobjaddr0)
+ so1Restored := state.GetStateObject(stateobjaddr1)
+ // non-deleted is equal (restored)
+ compareStateObjects(so0Restored, so0, t)
+ // deleted should be nil, both before and after restore of state copy
+ if so1Restored != nil {
+ t.Fatalf("deleted object not nil after restoring snapshot")
+ }
+}
+
+func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
+ if so0.address != so1.address {
+ t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
+ }
+ if so0.balance.Cmp(so1.balance) != 0 {
+ t.Fatalf("Balance mismatch: have %v, want %v", so0.balance, so1.balance)
+ }
+ if so0.nonce != so1.nonce {
+ t.Fatalf("Nonce mismatch: have %v, want %v", so0.nonce, so1.nonce)
+ }
+ if !bytes.Equal(so0.codeHash, so1.codeHash) {
+ t.Fatalf("CodeHash mismatch: have %v, want %v", so0.codeHash, so1.codeHash)
+ }
+ if !bytes.Equal(so0.code, so1.code) {
+ t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
+ }
+ if !bytes.Equal(so0.initCode, so1.initCode) {
+ t.Fatalf("InitCode mismatch: have %v, want %v", so0.initCode, so1.initCode)
+ }
+
+ for k, v := range so1.storage {
+ if so0.storage[k] != v {
+ t.Fatalf("Storage key %s mismatch: have %v, want %v", k, so0.storage[k], v)
+ }
+ }
+ for k, v := range so0.storage {
+ if so1.storage[k] != v {
+ t.Fatalf("Storage key %s mismatch: have %v, want none.", k, v)
+ }
+ }
+
+ if so0.gasPool.Cmp(so1.gasPool) != 0 {
+ t.Fatalf("GasPool mismatch: have %v, want %v", so0.gasPool, so1.gasPool)
+ }
+ if so0.remove != so1.remove {
+ t.Fatalf("Remove mismatch: have %v, want %v", so0.remove, so1.remove)
+ }
+ if so0.deleted != so1.deleted {
+ t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
+ }
+ if so0.dirty != so1.dirty {
+ t.Fatalf("Dirty mismatch: have %v, want %v", so0.dirty, so1.dirty)
+ }
+}
diff --git a/miner/agent.go b/miner/agent.go
index 2f8d9fee4..7ccf8d2e0 100644
--- a/miner/agent.go
+++ b/miner/agent.go
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/pow"
+ "sync/atomic"
)
type CpuAgent struct {
@@ -35,6 +36,8 @@ type CpuAgent struct {
index int
pow pow.PoW
+
+ isMining int32 // isMining indicates whether the agent is currently mining
}
func NewCpuAgent(index int, pow pow.PoW) *CpuAgent {
@@ -60,6 +63,10 @@ func (self *CpuAgent) Stop() {
func (self *CpuAgent) Start() {
self.mu.Lock()
defer self.mu.Unlock()
+
+ if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) {
+ return // agent already started
+ }
self.quit = make(chan struct{})
// creating current op ch makes sure we're not closing a nil ch
@@ -99,10 +106,11 @@ done:
case <-self.workCh:
default:
close(self.workCh)
-
break done
}
}
+
+ atomic.StoreInt32(&self.isMining, 0)
}
func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
diff --git a/rpc/comms/http.go b/rpc/comms/http.go
index c165aa27e..f4a930d0e 100644
--- a/rpc/comms/http.go
+++ b/rpc/comms/http.go
@@ -271,13 +271,13 @@ func (self *httpClient) Send(req interface{}) error {
reply, _ := ioutil.ReadAll(resp.Body)
var rpcSuccessResponse shared.SuccessResponse
if err = self.codec.Decode(reply, &rpcSuccessResponse); err == nil {
- self.lastRes = rpcSuccessResponse.Result
+ self.lastRes = &rpcSuccessResponse
self.lastErr = err
return nil
} else {
var rpcErrorResponse shared.ErrorResponse
if err = self.codec.Decode(reply, &rpcErrorResponse); err == nil {
- self.lastRes = rpcErrorResponse.Error
+ self.lastRes = &rpcErrorResponse
self.lastErr = err
return nil
} else {