aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/admin.go6
-rw-r--r--cmd/geth/js_test.go2
-rw-r--r--cmd/geth/main.go45
-rw-r--r--cmd/utils/cmd.go52
-rw-r--r--cmd/utils/flags.go2
-rw-r--r--core/block_processor.go14
-rw-r--r--core/block_processor_test.go6
-rw-r--r--core/chain_makers.go2
-rw-r--r--core/chain_manager.go99
-rw-r--r--core/chain_manager_test.go15
-rw-r--r--eth/backend.go4
-rw-r--r--miner/worker.go8
-rw-r--r--rpc/api.go22
-rw-r--r--xeth/xeth.go9
14 files changed, 217 insertions, 69 deletions
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index ebdf3512a..53dd0e6ad 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -383,7 +383,7 @@ func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
var passphrase string
if arg.IsUndefined() {
fmt.Println("Please enter a passphrase now.")
- passphrase, err = readPassword("Passphrase: ", true)
+ passphrase, err = utils.PromptPassword("Passphrase: ", true)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
@@ -410,12 +410,12 @@ func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
if arg.IsUndefined() {
fmt.Println("The new account will be encrypted with a passphrase.")
fmt.Println("Please enter a passphrase now.")
- auth, err := readPassword("Passphrase: ", true)
+ auth, err := utils.PromptPassword("Passphrase: ", true)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
- confirm, err := readPassword("Repeat Passphrase: ", false)
+ confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index e02e8f704..6368efbfc 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -172,6 +172,8 @@ func TestBlockChain(t *testing.T) {
tmpfile := filepath.Join(extmp, "export.chain")
tmpfileq := strconv.Quote(tmpfile)
+ ethereum.ChainManager().Reset()
+
checkEvalJSON(t, repl, `admin.export(`+tmpfileq+`)`, `true`)
if _, err := os.Stat(tmpfile); err != nil {
t.Fatal(err)
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index b0970212e..df0af3e79 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -21,7 +21,6 @@
package main
import (
- "bufio"
"fmt"
"io"
"io/ioutil"
@@ -44,7 +43,6 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
- "github.com/peterh/liner"
)
import _ "net/http/pprof"
@@ -230,6 +228,11 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
Name: "upgradedb",
Usage: "upgrade chainblock database",
},
+ {
+ Action: removeDb,
+ Name: "removedb",
+ Usage: "Remove blockchain and state databases",
+ },
}
app.Flags = []cli.Flag{
utils.IdentityFlag,
@@ -421,12 +424,12 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
if len(passfile) == 0 {
fmt.Println(desc)
- auth, err := readPassword("Passphrase: ", true)
+ auth, err := utils.PromptPassword("Passphrase: ", true)
if err != nil {
utils.Fatalf("%v", err)
}
if confirmation {
- confirm, err := readPassword("Repeat Passphrase: ", false)
+ confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
@@ -543,6 +546,25 @@ func exportchain(ctx *cli.Context) {
return
}
+func removeDb(ctx *cli.Context) {
+ confirm, err := utils.PromptConfirm("Remove local databases?")
+ if err != nil {
+ utils.Fatalf("%v", err)
+ }
+
+ if confirm {
+ fmt.Println("Removing chain and state databases...")
+ start := time.Now()
+
+ os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain"))
+ os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state"))
+
+ fmt.Printf("Removed in %v\n", time.Since(start))
+ } else {
+ fmt.Println("Operation aborted")
+ }
+}
+
func upgradeDb(ctx *cli.Context) {
fmt.Println("Upgrade blockchain DB")
@@ -666,18 +688,3 @@ func hashish(x string) bool {
_, err := strconv.Atoi(x)
return err != nil
}
-
-func readPassword(prompt string, warnTerm bool) (string, error) {
- if liner.TerminalSupported() {
- lr := liner.NewLiner()
- defer lr.Close()
- return lr.PasswordPrompt(prompt)
- }
- if warnTerm {
- fmt.Println("!! Unsupported terminal, password will be echoed.")
- }
- fmt.Print(prompt)
- input, err := bufio.NewReader(os.Stdin).ReadString('\n')
- fmt.Println()
- return input, err
-}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index fb55a64af..39b4e46da 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -22,11 +22,13 @@
package utils
import (
+ "bufio"
"fmt"
"io"
"os"
"os/signal"
"regexp"
+ "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@@ -35,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/peterh/liner"
)
var interruptCallbacks = []func(os.Signal){}
@@ -71,18 +74,45 @@ func openLogFile(Datadir string, filename string) *os.File {
return file
}
-func confirm(message string) bool {
- fmt.Println(message, "Are you sure? (y/n)")
- var r string
- fmt.Scanln(&r)
- for ; ; fmt.Scanln(&r) {
- if r == "n" || r == "y" {
- break
- } else {
- fmt.Printf("Yes or no? (%s)", r)
- }
+func PromptConfirm(prompt string) (bool, error) {
+ var (
+ input string
+ err error
+ )
+ prompt = prompt + " [y/N] "
+
+ if liner.TerminalSupported() {
+ lr := liner.NewLiner()
+ defer lr.Close()
+ input, err = lr.Prompt(prompt)
+ } else {
+ fmt.Print(prompt)
+ input, err = bufio.NewReader(os.Stdin).ReadString('\n')
+ fmt.Println()
+ }
+
+ if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" {
+ return true, nil
+ } else {
+ return false, nil
+ }
+
+ return false, err
+}
+
+func PromptPassword(prompt string, warnTerm bool) (string, error) {
+ if liner.TerminalSupported() {
+ lr := liner.NewLiner()
+ defer lr.Close()
+ return lr.PasswordPrompt(prompt)
+ }
+ if warnTerm {
+ fmt.Println("!! Unsupported terminal, password will be echoed.")
}
- return r == "y"
+ fmt.Print(prompt)
+ input, err := bufio.NewReader(os.Stdin).ReadString('\n')
+ fmt.Println()
+ return input, err
}
func initDataDir(Datadir string) {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 6ec4fdc55..f646e4fcc 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -336,8 +336,8 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
}
eventMux := new(event.TypeMux)
- chainManager := core.NewChainManager(blockDb, stateDb, eventMux)
pow := ethash.New()
+ chainManager := core.NewChainManager(blockDb, stateDb, pow, eventMux)
txPool := core.NewTxPool(eventMux, chainManager.State, chainManager.GasLimit)
blockProcessor := core.NewBlockProcessor(stateDb, extraDb, pow, txPool, chainManager, eventMux)
chainManager.SetProcessor(blockProcessor)
diff --git a/core/block_processor.go b/core/block_processor.go
index 0652d217f..20e6722a4 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -188,7 +188,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
state := state.New(parent.Root(), sm.db)
// Block validation
- if err = sm.ValidateHeader(block.Header(), parent.Header()); err != nil {
+ if err = sm.ValidateHeader(block.Header(), parent.Header(), false); err != nil {
return
}
@@ -268,7 +268,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
// Validates the current block. Returns an error if the block was invalid,
// an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult)
-func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
+func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error {
if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
}
@@ -299,9 +299,11 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
}
- // Verify the nonce of the block. Return an error if it's not valid
- if !sm.Pow.Verify(types.NewBlockWithHeader(block)) {
- return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
+ if checkPow {
+ // Verify the nonce of the block. Return an error if it's not valid
+ if !sm.Pow.Verify(types.NewBlockWithHeader(block)) {
+ return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
+ }
}
return nil
@@ -375,7 +377,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
return UncleError("uncle[%d](%x)'s parent unknown (%x)", i, hash[:4], uncle.ParentHash[0:4])
}
- if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash]); err != nil {
+ if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash], true); err != nil {
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
}
}
diff --git a/core/block_processor_test.go b/core/block_processor_test.go
index 02524a4c1..e0aa5fb4c 100644
--- a/core/block_processor_test.go
+++ b/core/block_processor_test.go
@@ -14,7 +14,7 @@ func proc() (*BlockProcessor, *ChainManager) {
db, _ := ethdb.NewMemDatabase()
var mux event.TypeMux
- chainMan := NewChainManager(db, db, &mux)
+ chainMan := NewChainManager(db, db, thePow(), &mux)
return NewBlockProcessor(db, db, ezp.New(), nil, chainMan, &mux), chainMan
}
@@ -24,13 +24,13 @@ func TestNumber(t *testing.T) {
block1.Header().Number = big.NewInt(3)
block1.Header().Time--
- err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header())
+ err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false)
if err != BlockNumberErr {
t.Errorf("expected block number error %v", err)
}
block1 = chain.NewBlock(common.Address{})
- err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header())
+ err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false)
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index acf7b39cc..44f17cc33 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -109,7 +109,7 @@ func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Dat
// Effectively a fork factory
func newChainManager(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager {
genesis := GenesisBlock(db)
- bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux}
+ bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux, pow: FakePow{}}
bc.txState = state.ManageState(state.New(genesis.Root(), db))
bc.futureBlocks = NewBlockCache(1000)
if block == nil {
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 62e518ca0..4fb7506e5 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"math/big"
+ "runtime"
"sync"
"time"
@@ -15,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -100,9 +102,11 @@ type ChainManager struct {
quit chan struct{}
wg sync.WaitGroup
+
+ pow pow.PoW
}
-func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *ChainManager {
+func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.TypeMux) *ChainManager {
bc := &ChainManager{
blockDb: blockDb,
stateDb: stateDb,
@@ -110,6 +114,7 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai
eventMux: mux,
quit: make(chan struct{}),
cache: NewBlockCache(blockCacheLimit),
+ pow: pow,
}
bc.setLastState()
@@ -343,7 +348,7 @@ func (self *ChainManager) Export(w io.Writer) error {
last := self.currentBlock.NumberU64()
- for nr := uint64(0); nr <= last; nr++ {
+ for nr := uint64(1); nr <= last; nr++ {
block := self.GetBlockByNumber(nr)
if block == nil {
return fmt.Errorf("export failed on #%d: not found", nr)
@@ -407,9 +412,11 @@ func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (
}
func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
- if block := self.cache.Get(hash); block != nil {
- return block
- }
+ /*
+ if block := self.cache.Get(hash); block != nil {
+ return block
+ }
+ */
data, _ := self.blockDb.Get(append(blockHashPre, hash[:]...))
if len(data) == 0 {
@@ -529,10 +536,19 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
stats struct{ queued, processed, ignored int }
tstart = time.Now()
)
+
+ // check the nonce in parallel to the block processing
+ // this speeds catching up significantly
+ nonceErrCh := make(chan error)
+ go func() {
+ nonceErrCh <- verifyNonces(self.pow, chain)
+ }()
+
for i, block := range chain {
if block == nil {
continue
}
+
// Setting block.Td regardless of error (known for example) prevents errors down the line
// in the protocol handler
block.Td = new(big.Int).Set(CalcTD(block, self.GetBlock(block.ParentHash())))
@@ -562,11 +578,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
continue
}
- h := block.Header()
-
- glog.V(logger.Error).Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes())
- glog.V(logger.Error).Infoln(err)
- glog.V(logger.Debug).Infoln(block)
+ blockErr(block, err)
return i, err
}
@@ -620,6 +632,13 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
}
+ // check and wait for the nonce error channel and
+ // make sure no nonce error was thrown in the process
+ err := <-nonceErrCh
+ if err != nil {
+ return 0, err
+ }
+
if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) {
tend := time.Since(tstart)
start, end := chain[0], chain[len(chain)-1]
@@ -718,3 +737,63 @@ out:
}
}
}
+
+func blockErr(block *types.Block, err error) {
+ h := block.Header()
+ glog.V(logger.Error).Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes())
+ glog.V(logger.Error).Infoln(err)
+ glog.V(logger.Debug).Infoln(block)
+}
+
+// verifyNonces verifies nonces of the given blocks in parallel and returns
+// an error if one of the blocks nonce verifications failed.
+func verifyNonces(pow pow.PoW, blocks []*types.Block) error {
+ // Spawn a few workers. They listen for blocks on the in channel
+ // and send results on done. The workers will exit in the
+ // background when in is closed.
+ var (
+ in = make(chan *types.Block)
+ done = make(chan error, runtime.GOMAXPROCS(0))
+ )
+ defer close(in)
+ for i := 0; i < cap(done); i++ {
+ go verifyNonce(pow, in, done)
+ }
+ // Feed blocks to the workers, aborting at the first invalid nonce.
+ var (
+ running, i int
+ block *types.Block
+ sendin = in
+ )
+ for i < len(blocks) || running > 0 {
+ if i == len(blocks) {
+ // Disable sending to in.
+ sendin = nil
+ } else {
+ block = blocks[i]
+ i++
+ }
+ select {
+ case sendin <- block:
+ running++
+ case err := <-done:
+ running--
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// verifyNonce is a worker for the verifyNonces method. It will run until
+// in is closed.
+func verifyNonce(pow pow.PoW, in <-chan *types.Block, done chan<- error) {
+ for block := range in {
+ if !pow.Verify(block) {
+ done <- ValidationError("Block(#%v) nonce is invalid (= %x)", block.Number(), block.Nonce)
+ } else {
+ done <- nil
+ }
+ }
+}
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index b5155e223..56bef24f3 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -9,11 +9,13 @@ import (
"strconv"
"testing"
+ "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -21,6 +23,11 @@ func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
}
+func thePow() pow.PoW {
+ pow, _ := ethash.NewForTesting()
+ return pow
+}
+
// Test fork of length N starting from block i
func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) {
// switch databases to process the new chain
@@ -259,7 +266,7 @@ func TestChainInsertions(t *testing.T) {
}
var eventMux event.TypeMux
- chainMan := NewChainManager(db, db, &eventMux)
+ chainMan := NewChainManager(db, db, thePow(), &eventMux)
txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) })
blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux)
chainMan.SetProcessor(blockMan)
@@ -305,7 +312,7 @@ func TestChainMultipleInsertions(t *testing.T) {
}
}
var eventMux event.TypeMux
- chainMan := NewChainManager(db, db, &eventMux)
+ chainMan := NewChainManager(db, db, thePow(), &eventMux)
txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) })
blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux)
chainMan.SetProcessor(blockMan)
@@ -334,7 +341,7 @@ func TestGetAncestors(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
var eventMux event.TypeMux
- chainMan := NewChainManager(db, db, &eventMux)
+ chainMan := NewChainManager(db, db, thePow(), &eventMux)
chain, err := loadChain("valid1", t)
if err != nil {
fmt.Println(err)
@@ -372,7 +379,7 @@ func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block
func chm(genesis *types.Block, db common.Database) *ChainManager {
var eventMux event.TypeMux
- bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux}
+ bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}}
bc.cache = NewBlockCache(100)
bc.futureBlocks = NewBlockCache(100)
bc.processor = bproc{}
diff --git a/eth/backend.go b/eth/backend.go
index a7107f8d8..519a4c410 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -266,9 +266,9 @@ func New(config *Config) (*Ethereum, error) {
MinerThreads: config.MinerThreads,
}
- eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.EventMux())
- eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
eth.pow = ethash.New()
+ eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.pow, eth.EventMux())
+ eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
eth.chainManager.SetProcessor(eth.blockProcessor)
diff --git a/miner/worker.go b/miner/worker.go
index d5f9dd8c5..5fa5d3777 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -224,7 +224,13 @@ func (self *worker) wait() {
}
self.mux.Post(core.NewMinedBlockEvent{block})
- glog.V(logger.Info).Infof("🔨 Mined block #%v", block.Number())
+ var stale string
+ canonBlock := self.chain.GetBlockByNumber(block.NumberU64())
+ if canonBlock != nil && canonBlock.Hash() != block.Hash() {
+ stale = "stale-"
+ }
+
+ glog.V(logger.Info).Infof("🔨 Mined %sblock #%v (%x)", stale, block.Number(), block.Hash().Bytes()[:4])
jsonlogger.LogJson(&logger.EthMinerNewBlock{
BlockHash: block.Hash().Hex(),
diff --git a/rpc/api.go b/rpc/api.go
index b59253ef7..0c1409d71 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -1,9 +1,9 @@
package rpc
import (
+ "bytes"
"encoding/json"
"math/big"
- // "sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
@@ -230,7 +230,14 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
block := api.xeth().EthBlockByNumber(args.BlockNumber)
br := NewBlockRes(block, args.IncludeTxs)
-
+ // If request was for "pending", nil nonsensical fields
+ if args.BlockNumber == -2 {
+ br.BlockHash = nil
+ br.BlockNumber = nil
+ br.Miner = nil
+ br.Nonce = nil
+ br.LogsBloom = nil
+ }
*reply = br
case "eth_getTransactionByHash":
args := new(HashArgs)
@@ -240,9 +247,12 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
tx, bhash, bnum, txi := api.xeth().EthTransactionByHash(args.Hash)
if tx != nil {
v := NewTransactionRes(tx)
- v.BlockHash = newHexData(bhash)
- v.BlockNumber = newHexNum(bnum)
- v.TxIndex = newHexNum(txi)
+ // if the blockhash is 0, assume this is a pending transaction
+ if bytes.Compare(bhash.Bytes(), bytes.Repeat([]byte{0}, 32)) != 0 {
+ v.BlockHash = newHexData(bhash)
+ v.BlockNumber = newHexNum(bnum)
+ v.TxIndex = newHexNum(txi)
+ }
*reply = v
}
case "eth_getTransactionByBlockHashAndIndex":
@@ -577,7 +587,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return NewNotImplementedError(req.Method)
}
- glog.V(logger.Detail).Infof("Reply: %T %s\n", reply, reply)
+ // glog.V(logger.Detail).Infof("Reply: %v\n", reply)
return nil
}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 88cd30afc..7de3e31be 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -304,6 +304,8 @@ func (self *XEth) EthBlockByHash(strHash string) *types.Block {
}
func (self *XEth) EthTransactionByHash(hash string) (tx *types.Transaction, blhash common.Hash, blnum *big.Int, txi uint64) {
+ // Due to increasing return params and need to determine if this is from transaction pool or
+ // some chain, this probably needs to be refactored for more expressiveness
data, _ := self.backend.ExtraDb().Get(common.FromHex(hash))
if len(data) != 0 {
tx = types.NewTransactionFromBytes(data)
@@ -357,7 +359,7 @@ func (self *XEth) Block(v interface{}) *Block {
return self.BlockByNumber(int64(n))
} else if str, ok := v.(string); ok {
return self.BlockByHash(str)
- } else if f, ok := v.(float64); ok { // Don't ask ...
+ } else if f, ok := v.(float64); ok { // JSON numbers are represented as float64
return self.BlockByNumber(int64(f))
}
@@ -778,7 +780,7 @@ func (self *XEth) PushTx(encodedTx string) (string, error) {
}
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) {
- statedb := self.State().State().Copy() //self.eth.ChainManager().TransState()
+ statedb := self.State().State().Copy()
var from *state.StateObject
if len(fromStr) == 0 {
accounts, err := self.backend.AccountManager().Accounts()
@@ -869,6 +871,7 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
contractCreation bool
)
+ // 2015-05-18 Is this still needed?
// TODO if no_private_key then
//if _, exists := p.register[args.From]; exists {
// p.register[args.From] = append(p.register[args.From], args)
@@ -924,9 +927,11 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
tx.SetNonce(nonce)
if err := self.sign(tx, from, false); err != nil {
+ state.RemoveNonce(from, tx.Nonce())
return "", err
}
if err := self.backend.TxPool().Add(tx); err != nil {
+ state.RemoveNonce(from, tx.Nonce())
return "", err
}