aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/blockchain.go29
-rw-r--r--eth/downloader/downloader.go6
-rw-r--r--eth/sync.go7
-rw-r--r--rpc/api/eth_args.go14
-rw-r--r--rpc/comms/comms.go11
5 files changed, 45 insertions, 22 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index f14ff363c..cea346e38 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -411,11 +411,14 @@ func (self *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
// insert injects a new head block into the current block chain. This method
// assumes that the block is indeed a true head. It will also reset the head
-// header and the head fast sync block to this very same block to prevent them
-// from pointing to a possibly old canonical chain (i.e. side chain by now).
+// header and the head fast sync block to this very same block if they are older
+// or if they are on a different side chain.
//
// Note, this function assumes that the `mu` mutex is held!
func (bc *BlockChain) insert(block *types.Block) {
+ // If the block is on a side chain or an unknown one, force other heads onto it too
+ updateHeads := GetCanonicalHash(bc.chainDb, block.NumberU64()) != block.Hash()
+
// Add the block to the canonical chain number scheme and mark as the head
if err := WriteCanonicalHash(bc.chainDb, block.Hash(), block.NumberU64()); err != nil {
glog.Fatalf("failed to insert block number: %v", err)
@@ -423,16 +426,20 @@ func (bc *BlockChain) insert(block *types.Block) {
if err := WriteHeadBlockHash(bc.chainDb, block.Hash()); err != nil {
glog.Fatalf("failed to insert head block hash: %v", err)
}
- if err := WriteHeadHeaderHash(bc.chainDb, block.Hash()); err != nil {
- glog.Fatalf("failed to insert head header hash: %v", err)
- }
- if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil {
- glog.Fatalf("failed to insert head fast block hash: %v", err)
- }
- // Update the internal state with the head block
bc.currentBlock = block
- bc.currentHeader = block.Header()
- bc.currentFastBlock = block
+
+ // If the block is better than out head or is on a different chain, force update heads
+ if updateHeads {
+ if err := WriteHeadHeaderHash(bc.chainDb, block.Hash()); err != nil {
+ glog.Fatalf("failed to insert head header hash: %v", err)
+ }
+ bc.currentHeader = block.Header()
+
+ if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil {
+ glog.Fatalf("failed to insert head fast block hash: %v", err)
+ }
+ bc.currentFastBlock = block
+ }
}
// Accessors
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 4bcbd8557..153427ee4 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -248,10 +248,11 @@ func (d *Downloader) UnregisterPeer(id string) error {
// Synchronise tries to sync up our local block chain with a remote peer, both
// adding various sanity checks as well as wrapping it with various log entries.
-func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) {
+func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error {
glog.V(logger.Detail).Infof("Attempting synchronisation: %v, head [%x…], TD %v", id, head[:4], td)
- switch err := d.synchronise(id, head, td, mode); err {
+ err := d.synchronise(id, head, td, mode)
+ switch err {
case nil:
glog.V(logger.Detail).Infof("Synchronisation completed")
@@ -268,6 +269,7 @@ func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode
default:
glog.V(logger.Warn).Infof("Synchronisation failed: %v", err)
}
+ return err
}
// synchronise will select the peer and use it for synchronising. If an empty string is given
diff --git a/eth/sync.go b/eth/sync.go
index b69a24556..bbf2abc04 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -170,13 +170,16 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
if pm.fastSync {
mode = downloader.FastSync
}
- pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode)
-
+ if err := pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode); err != nil {
+ return
+ }
// If fast sync was enabled, and we synced up, disable it
if pm.fastSync {
+ // Wait until all pending imports finish processing
for pm.downloader.Synchronising() {
time.Sleep(100 * time.Millisecond)
}
+ // Disable fast sync if we indeed have something in our chain
if pm.blockchain.CurrentBlock().NumberU64() > 0 {
glog.V(logger.Info).Infof("fast sync complete, auto disabling")
pm.fastSync = false
diff --git a/rpc/api/eth_args.go b/rpc/api/eth_args.go
index 6aca6a663..457350d74 100644
--- a/rpc/api/eth_args.go
+++ b/rpc/api/eth_args.go
@@ -626,7 +626,12 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
args.IncludeTxs = obj[1].(bool)
- return nil
+ if inclTx, ok := obj[1].(bool); ok {
+ args.IncludeTxs = inclTx
+ return nil
+ }
+
+ return shared.NewInvalidTypeError("includeTxs", "not a bool")
}
type GetBlockByNumberArgs struct {
@@ -648,9 +653,12 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
return err
}
- args.IncludeTxs = obj[1].(bool)
+ if inclTx, ok := obj[1].(bool); ok {
+ args.IncludeTxs = inclTx
+ return nil
+ }
- return nil
+ return shared.NewInvalidTypeError("includeTxs", "not a bool")
}
type BlockFilterArgs struct {
diff --git a/rpc/comms/comms.go b/rpc/comms/comms.go
index 731b2f62e..61fba5722 100644
--- a/rpc/comms/comms.go
+++ b/rpc/comms/comms.go
@@ -62,13 +62,18 @@ type EthereumClient interface {
func handle(id int, conn net.Conn, api shared.EthereumApi, c codec.Codec) {
codec := c.New(conn)
+ defer func() {
+ if r := recover(); r != nil {
+ glog.Errorf("panic: %v\n", r)
+ }
+ codec.Close()
+ }()
+
for {
requests, isBatch, err := codec.ReadRequest()
if err == io.EOF {
- codec.Close()
return
} else if err != nil {
- codec.Close()
glog.V(logger.Debug).Infof("Closed IPC Conn %06d recv err - %v\n", id, err)
return
}
@@ -87,7 +92,6 @@ func handle(id int, conn net.Conn, api shared.EthereumApi, c codec.Codec) {
err = codec.WriteResponse(responses[:responseCount])
if err != nil {
- codec.Close()
glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err)
return
}
@@ -98,7 +102,6 @@ func handle(id int, conn net.Conn, api shared.EthereumApi, c codec.Codec) {
rpcResponse = shared.NewRpcResponse(requests[0].Id, requests[0].Jsonrpc, res, err)
err = codec.WriteResponse(rpcResponse)
if err != nil {
- codec.Close()
glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err)
return
}