aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/disasm/main.go2
-rw-r--r--cmd/ethereum/admin.go2
-rw-r--r--cmd/ethereum/blocktest.go28
-rw-r--r--cmd/ethereum/js.go1
-rw-r--r--cmd/ethereum/main.go2
-rw-r--r--cmd/ethtest/main.go6
-rw-r--r--cmd/evm/main.go4
-rw-r--r--cmd/mist/bindings.go2
-rw-r--r--cmd/utils/flags.go2
-rw-r--r--core/asm.go2
-rw-r--r--core/block_cache.go5
-rw-r--r--core/block_processor.go38
-rw-r--r--core/chain_makers.go2
-rw-r--r--core/chain_manager.go49
-rw-r--r--core/error.go5
-rw-r--r--core/events.go6
-rw-r--r--core/execution.go4
-rw-r--r--core/filter.go2
-rw-r--r--core/genesis.go2
-rw-r--r--core/state/dump.go (renamed from state/dump.go)0
-rw-r--r--core/state/errors.go (renamed from state/errors.go)0
-rw-r--r--core/state/log.go (renamed from state/log.go)0
-rw-r--r--core/state/main_test.go (renamed from state/main_test.go)0
-rw-r--r--core/state/managed_state.go (renamed from state/managed_state.go)0
-rw-r--r--core/state/managed_state_test.go (renamed from state/managed_state_test.go)0
-rw-r--r--core/state/state_object.go (renamed from state/state_object.go)0
-rw-r--r--core/state/state_test.go (renamed from state/state_test.go)0
-rw-r--r--core/state/statedb.go (renamed from state/statedb.go)0
-rw-r--r--core/state_transition.go4
-rw-r--r--core/transaction_pool_test.go2
-rw-r--r--core/types/bloom9.go2
-rw-r--r--core/types/bloom9_test.go2
-rw-r--r--core/types/common.go2
-rw-r--r--core/types/receipt.go2
-rw-r--r--core/vm/address.go (renamed from vm/address.go)0
-rw-r--r--core/vm/analysis.go (renamed from vm/analysis.go)0
-rw-r--r--core/vm/asm.go (renamed from vm/asm.go)0
-rw-r--r--core/vm/common.go (renamed from vm/common.go)0
-rw-r--r--core/vm/context.go (renamed from vm/context.go)0
-rw-r--r--core/vm/environment.go (renamed from vm/environment.go)2
-rw-r--r--core/vm/errors.go (renamed from vm/errors.go)0
-rw-r--r--core/vm/gas.go (renamed from vm/gas.go)0
-rw-r--r--core/vm/main_test.go (renamed from vm/main_test.go)0
-rw-r--r--core/vm/memory.go (renamed from vm/memory.go)0
-rw-r--r--core/vm/stack.go (renamed from vm/stack.go)0
-rw-r--r--core/vm/types.go (renamed from vm/types.go)0
-rw-r--r--core/vm/virtual_machine.go (renamed from vm/virtual_machine.go)0
-rw-r--r--core/vm/vm.go (renamed from vm/vm.go)2
-rw-r--r--core/vm/vm_jit.go (renamed from vm/vm_jit.go)2
-rw-r--r--core/vm/vm_jit_fake.go (renamed from vm/vm_jit_fake.go)0
-rw-r--r--core/vm/vm_test.go (renamed from vm/vm_test.go)0
-rw-r--r--core/vm_env.go4
-rw-r--r--eth/backend.go2
-rw-r--r--event/filter/eth_filter.go2
-rw-r--r--miner/remote_agent.go2
-rw-r--r--miner/worker.go80
-rw-r--r--rpc/api.go37
-rw-r--r--rpc/api_test.go46
-rw-r--r--rpc/args.go103
-rw-r--r--rpc/args_test.go74
-rw-r--r--rpc/responses.go2
-rw-r--r--tests/blocktest.go35
-rw-r--r--tests/helper/vm.go4
-rw-r--r--tests/vm/gh_test.go2
-rw-r--r--vm/.ethtest0
-rw-r--r--xeth/state.go2
-rw-r--r--xeth/types.go2
-rw-r--r--xeth/xeth.go17
68 files changed, 460 insertions, 138 deletions
diff --git a/cmd/disasm/main.go b/cmd/disasm/main.go
index 5d42121b6..5b658046f 100644
--- a/cmd/disasm/main.go
+++ b/cmd/disasm/main.go
@@ -6,7 +6,7 @@ import (
"os"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/vm"
)
func main() {
diff --git a/cmd/ethereum/admin.go b/cmd/ethereum/admin.go
index 65adb4086..139395dad 100644
--- a/cmd/ethereum/admin.go
+++ b/cmd/ethereum/admin.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/xeth"
"github.com/robertkrimen/otto"
)
diff --git a/cmd/ethereum/blocktest.go b/cmd/ethereum/blocktest.go
index e6d701d2c..d9cdfa83f 100644
--- a/cmd/ethereum/blocktest.go
+++ b/cmd/ethereum/blocktest.go
@@ -5,9 +5,9 @@ import (
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/tests"
)
@@ -26,10 +26,10 @@ be able to interact with the chain defined by the test.
}
func runblocktest(ctx *cli.Context) {
- if len(ctx.Args()) != 2 {
- utils.Fatalf("This command requires two arguments.")
+ if len(ctx.Args()) != 3 {
+ utils.Fatalf("Usage: ethereum blocktest <path-to-test-file> <test-name> {rpc, norpc}")
}
- file, testname := ctx.Args()[0], ctx.Args()[1]
+ file, testname, startrpc := ctx.Args()[0], ctx.Args()[1], ctx.Args()[2]
bt, err := tests.LoadBlockTests(file)
if err != nil {
@@ -42,6 +42,7 @@ func runblocktest(ctx *cli.Context) {
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }
+ cfg.MaxPeers = 0 // disable network
ethereum, err := eth.New(cfg)
if err != nil {
utils.Fatalf("%v", err)
@@ -51,7 +52,8 @@ func runblocktest(ctx *cli.Context) {
ethereum.ResetWithGenesisBlock(test.Genesis)
// import pre accounts
- if err := test.InsertPreState(ethereum.StateDb()); err != nil {
+ statedb, err := test.InsertPreState(ethereum.StateDb())
+ if err != nil {
utils.Fatalf("could not insert genesis accounts: %v", err)
}
@@ -60,7 +62,19 @@ func runblocktest(ctx *cli.Context) {
if err := chain.InsertChain(test.Blocks); err != nil {
utils.Fatalf("Block Test load error: %v", err)
} else {
- fmt.Println("Block Test chain loaded, starting ethereum.")
+ fmt.Println("Block Test chain loaded")
+ }
+
+ if err := test.ValidatePostState(statedb); err != nil {
+ utils.Fatalf("post state validation failed: %v", err)
+ }
+ fmt.Println("Block Test post state validated, starting ethereum.")
+
+ if startrpc == "rpc" {
+ startEth(ctx, ethereum)
+ utils.StartRPC(ethereum, ctx)
+ ethereum.WaitForShutdown()
+ } else {
+ startEth(ctx, ethereum)
}
- startEth(ctx, ethereum)
}
diff --git a/cmd/ethereum/js.go b/cmd/ethereum/js.go
index 88d16d6a8..6f0ac526f 100644
--- a/cmd/ethereum/js.go
+++ b/cmd/ethereum/js.go
@@ -91,6 +91,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre {
func (js *jsre) apiBindings() {
ethApi := rpc.NewEthereumApi(js.xeth, js.ethereum.DataDir)
+ ethApi.Close()
//js.re.Bind("jeth", rpc.NewJeth(ethApi, js.re.ToVal))
jeth := rpc.NewJeth(ethApi, js.re.ToVal, js.re)
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index e351453b1..5ad4c0a4e 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -36,7 +36,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/peterh/liner"
)
diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go
index f2f7d27f3..f5b423e8d 100644
--- a/cmd/ethtest/main.go
+++ b/cmd/ethtest/main.go
@@ -36,9 +36,9 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/tests/helper"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/vm"
)
type Log struct {
@@ -219,7 +219,7 @@ func RunVmTest(r io.Reader) (failed int) {
}
func main() {
- helper.Logger.SetLogLevel(5)
+ //helper.Logger.SetLogLevel(5)
vm.Debug = true
if len(os.Args) > 1 {
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index 17137e4bb..76e34e21d 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -35,8 +35,8 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/state"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
)
var (
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index 5d45d927e..8a9ec7cb1 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -28,7 +28,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type plugin struct {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index f87d25ce9..9a4ab5804 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -256,7 +256,7 @@ func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
addr := ctx.GlobalString(RPCListenAddrFlag.Name)
port := ctx.GlobalInt(RPCPortFlag.Name)
dataDir := ctx.GlobalString(DataDirFlag.Name)
-
+ fmt.Println("Starting RPC on port: ", port)
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
if err != nil {
Fatalf("Can't listen on %s:%d: %v", addr, port, err)
diff --git a/core/asm.go b/core/asm.go
index fc3493fe1..f40c07904 100644
--- a/core/asm.go
+++ b/core/asm.go
@@ -5,7 +5,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/vm"
)
func Disassemble(script []byte) (asm []string) {
diff --git a/core/block_cache.go b/core/block_cache.go
index 321021eb4..ea39e78e8 100644
--- a/core/block_cache.go
+++ b/core/block_cache.go
@@ -66,3 +66,8 @@ func (bc *BlockCache) Get(hash common.Hash) *types.Block {
return nil
}
+
+func (bc *BlockCache) Has(hash common.Hash) bool {
+ _, ok := bc.blocks[hash]
+ return ok
+}
diff --git a/core/block_processor.go b/core/block_processor.go
index 99c5fea05..4bcede85e 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"gopkg.in/fatih/set.v0"
)
@@ -166,9 +166,15 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// Create a new state based on the parent's root (e.g., create copy)
state := state.New(parent.Root(), sm.db)
+ // track (possible) uncle block
+ var uncle bool
// Block validation
if err = sm.ValidateHeader(block.Header(), parent.Header()); err != nil {
- return
+ if err != BlockEqualTSErr {
+ return
+ }
+ err = nil
+ uncle = true
}
// There can be at most two uncles
@@ -223,14 +229,22 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
td = CalculateTD(block, parent)
// Sync the current block's state to the database
state.Sync()
- // Remove transactions from the pool
- sm.txpool.RemoveSet(block.Transactions())
+
+ if !uncle {
+ // Remove transactions from the pool
+ sm.txpool.RemoveSet(block.Transactions())
+ }
for _, tx := range block.Transactions() {
putTx(sm.extraDb, tx)
}
- chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash().Bytes()[0:4])
+ if uncle {
+ chainlogger.Infof("found possible uncle block #%d (%x...)\n", header.Number, block.Hash().Bytes()[0:4])
+ return td, nil, BlockEqualTSErr
+ } else {
+ chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash().Bytes()[0:4])
+ }
return td, state.Logs(), nil
}
@@ -255,10 +269,6 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
}
- if block.Time <= parent.Time {
- return ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
- }
-
if int64(block.Time) > time.Now().Unix() {
return BlockFutureErr
}
@@ -272,6 +282,10 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
}
+ if block.Time <= parent.Time {
+ return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
+ }
+
return nil
}
@@ -307,14 +321,10 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
- if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash]); err != nil {
+ if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash]); err != nil && err != BlockEqualTSErr {
return ValidationError(fmt.Sprintf("%v", err))
}
- if !sm.Pow.Verify(types.NewBlockWithHeader(uncle)) {
- return ValidationError("Uncle's nonce is invalid (= %x)", uncle.Nonce)
- }
-
r := new(big.Int)
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
diff --git a/core/chain_makers.go b/core/chain_makers.go
index e3001331c..d559b2a3a 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
// So we can generate blocks easily
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 1bc8edea6..3e030838a 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
var (
@@ -32,8 +32,10 @@ type StateQuery interface {
func CalcDifficulty(block, parent *types.Header) *big.Int {
diff := new(big.Int)
- min := big.NewInt(2048)
- adjust := new(big.Int).Div(parent.Difficulty, min)
+ diffBoundDiv := big.NewInt(2048)
+ min := big.NewInt(131072)
+
+ adjust := new(big.Int).Div(parent.Difficulty, diffBoundDiv)
if (block.Time - parent.Time) < 8 {
diff.Add(parent.Difficulty, adjust)
} else {
@@ -106,12 +108,7 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai
// Take ownership of this particular state
bc.txState = state.ManageState(bc.State().Copy())
- // load in last `blockCacheLimit` - 1 blocks. Last block is the current.
- ancestors := bc.GetAncestors(bc.currentBlock, blockCacheLimit-1)
- ancestors = append(ancestors, bc.currentBlock)
- for _, block := range ancestors {
- bc.cache.Push(block)
- }
+ bc.makeCache()
go bc.update()
@@ -194,6 +191,18 @@ func (bc *ChainManager) setLastBlock() {
chainlogger.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td)
}
+func (bc *ChainManager) makeCache() {
+ if bc.cache == nil {
+ bc.cache = NewBlockCache(blockCacheLimit)
+ }
+ // load in last `blockCacheLimit` - 1 blocks. Last block is the current.
+ ancestors := bc.GetAncestors(bc.currentBlock, blockCacheLimit-1)
+ ancestors = append(ancestors, bc.currentBlock)
+ for _, block := range ancestors {
+ bc.cache.Push(block)
+ }
+}
+
// Block creation & chain handling
func (bc *ChainManager) NewBlock(coinbase common.Address) *types.Block {
bc.mu.RLock()
@@ -240,10 +249,15 @@ func (bc *ChainManager) Reset() {
bc.removeBlock(block)
}
+ if bc.cache == nil {
+ bc.cache = NewBlockCache(blockCacheLimit)
+ }
+
// Prepare the genesis block
bc.write(bc.genesisBlock)
bc.insert(bc.genesisBlock)
bc.currentBlock = bc.genesisBlock
+ bc.makeCache()
bc.setTotalDifficulty(common.Big("0"))
}
@@ -265,6 +279,7 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
bc.write(bc.genesisBlock)
bc.insert(bc.genesisBlock)
bc.currentBlock = bc.genesisBlock
+ bc.makeCache()
}
// Export writes the active chain to the given writer.
@@ -434,9 +449,14 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
continue
}
+ if err == BlockEqualTSErr {
+ queue[i] = ChainSideEvent{block, logs}
+ continue
+ }
+
h := block.Header()
- chainlogger.Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes()[:4])
- chainlogger.Infoln(err)
+ chainlogger.Errorf("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes()[:4])
+ chainlogger.Errorln(err)
chainlogger.Debugln(block)
return err
}
@@ -522,10 +542,3 @@ out:
}
}
}
-
-/*
-// Satisfy state query interface
-func (self *ChainManager) GetAccount(addr common.Hash) *state.StateObject {
- return self.State().GetAccount(addr)
-}
-*/
diff --git a/core/error.go b/core/error.go
index f6ac26cff..0642948cd 100644
--- a/core/error.go
+++ b/core/error.go
@@ -9,8 +9,9 @@ import (
)
var (
- BlockNumberErr = errors.New("block number invalid")
- BlockFutureErr = errors.New("block time is in the future")
+ BlockNumberErr = errors.New("block number invalid")
+ BlockFutureErr = errors.New("block time is in the future")
+ BlockEqualTSErr = errors.New("block time stamp equal to previous")
)
// Parent error. In case a parent is unknown this error will be thrown
diff --git a/core/events.go b/core/events.go
index 8c5fb592a..3da668af5 100644
--- a/core/events.go
+++ b/core/events.go
@@ -2,7 +2,7 @@ package core
import (
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
// TxPreEvent is posted when a transaction enters the transaction pool.
@@ -38,6 +38,10 @@ type PendingBlockEvent struct {
Logs state.Logs
}
+type ChainUncleEvent struct {
+ Block *types.Block
+}
+
type ChainHeadEvent struct{ Block *types.Block }
// Mining operation events
diff --git a/core/execution.go b/core/execution.go
index 4f15fb42a..92d932a9f 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -6,8 +6,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/state"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
)
type Execution struct {
diff --git a/core/filter.go b/core/filter.go
index b5d9deb7a..901931d99 100644
--- a/core/filter.go
+++ b/core/filter.go
@@ -5,7 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type AccountChange struct {
diff --git a/core/genesis.go b/core/genesis.go
index 3e00533ae..e0d3e51b8 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
/*
diff --git a/state/dump.go b/core/state/dump.go
index 712f8da1f..712f8da1f 100644
--- a/state/dump.go
+++ b/core/state/dump.go
diff --git a/state/errors.go b/core/state/errors.go
index 5a847d38b..5a847d38b 100644
--- a/state/errors.go
+++ b/core/state/errors.go
diff --git a/state/log.go b/core/state/log.go
index f8aa4c08c..f8aa4c08c 100644
--- a/state/log.go
+++ b/core/state/log.go
diff --git a/state/main_test.go b/core/state/main_test.go
index f3d3f7e23..f3d3f7e23 100644
--- a/state/main_test.go
+++ b/core/state/main_test.go
diff --git a/state/managed_state.go b/core/state/managed_state.go
index 0fcc1be67..0fcc1be67 100644
--- a/state/managed_state.go
+++ b/core/state/managed_state.go
diff --git a/state/managed_state_test.go b/core/state/managed_state_test.go
index b61f59e6d..b61f59e6d 100644
--- a/state/managed_state_test.go
+++ b/core/state/managed_state_test.go
diff --git a/state/state_object.go b/core/state/state_object.go
index a7c20722c..a7c20722c 100644
--- a/state/state_object.go
+++ b/core/state/state_object.go
diff --git a/state/state_test.go b/core/state/state_test.go
index a3d3973de..a3d3973de 100644
--- a/state/state_test.go
+++ b/core/state/state_test.go
diff --git a/state/statedb.go b/core/state/statedb.go
index 6fcd39dbc..6fcd39dbc 100644
--- a/state/statedb.go
+++ b/core/state/statedb.go
diff --git a/core/state_transition.go b/core/state_transition.go
index d0b2c5d7c..e530567d0 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -6,8 +6,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/state"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
)
const tryJit = false
diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go
index bf9012573..a009a4c9d 100644
--- a/core/transaction_pool_test.go
+++ b/core/transaction_pool_test.go
@@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
// State query interface
diff --git a/core/types/bloom9.go b/core/types/bloom9.go
index 64a8ff49a..af90679ce 100644
--- a/core/types/bloom9.go
+++ b/core/types/bloom9.go
@@ -5,7 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
func CreateBloom(receipts Receipts) Bloom {
diff --git a/core/types/bloom9_test.go b/core/types/bloom9_test.go
index 0841bb859..3c95772ec 100644
--- a/core/types/bloom9_test.go
+++ b/core/types/bloom9_test.go
@@ -4,7 +4,7 @@ package types
import (
"testing"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
func TestBloom9(t *testing.T) {
diff --git a/core/types/common.go b/core/types/common.go
index ce1090919..4397d4938 100644
--- a/core/types/common.go
+++ b/core/types/common.go
@@ -4,7 +4,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"fmt"
)
diff --git a/core/types/receipt.go b/core/types/receipt.go
index f88d42b29..83c981f93 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type Receipt struct {
diff --git a/vm/address.go b/core/vm/address.go
index 215f4bc8f..215f4bc8f 100644
--- a/vm/address.go
+++ b/core/vm/address.go
diff --git a/vm/analysis.go b/core/vm/analysis.go
index 411df5686..411df5686 100644
--- a/vm/analysis.go
+++ b/core/vm/analysis.go
diff --git a/vm/asm.go b/core/vm/asm.go
index 83fcb0e08..83fcb0e08 100644
--- a/vm/asm.go
+++ b/core/vm/asm.go
diff --git a/vm/common.go b/core/vm/common.go
index 8d8f4253f..8d8f4253f 100644
--- a/vm/common.go
+++ b/core/vm/common.go
diff --git a/vm/context.go b/core/vm/context.go
index e73199b77..e73199b77 100644
--- a/vm/context.go
+++ b/core/vm/context.go
diff --git a/vm/environment.go b/core/vm/environment.go
index 5d493166c..a0a18a99b 100644
--- a/vm/environment.go
+++ b/core/vm/environment.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type Environment interface {
diff --git a/vm/errors.go b/core/vm/errors.go
index ab011bd62..ab011bd62 100644
--- a/vm/errors.go
+++ b/core/vm/errors.go
diff --git a/vm/gas.go b/core/vm/gas.go
index c4d5e4c4e..c4d5e4c4e 100644
--- a/vm/gas.go
+++ b/core/vm/gas.go
diff --git a/vm/main_test.go b/core/vm/main_test.go
index 0ae03bf6a..0ae03bf6a 100644
--- a/vm/main_test.go
+++ b/core/vm/main_test.go
diff --git a/vm/memory.go b/core/vm/memory.go
index dd47fa1b5..dd47fa1b5 100644
--- a/vm/memory.go
+++ b/core/vm/memory.go
diff --git a/vm/stack.go b/core/vm/stack.go
index c5c2774db..c5c2774db 100644
--- a/vm/stack.go
+++ b/core/vm/stack.go
diff --git a/vm/types.go b/core/vm/types.go
index 1ea80a212..1ea80a212 100644
--- a/vm/types.go
+++ b/core/vm/types.go
diff --git a/vm/virtual_machine.go b/core/vm/virtual_machine.go
index 6db284f42..6db284f42 100644
--- a/vm/virtual_machine.go
+++ b/core/vm/virtual_machine.go
diff --git a/vm/vm.go b/core/vm/vm.go
index 7400a48c4..f4bf1ca72 100644
--- a/vm/vm.go
+++ b/core/vm/vm.go
@@ -6,7 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type Vm struct {
diff --git a/vm/vm_jit.go b/core/vm/vm_jit.go
index 9d26957f0..2b88d8620 100644
--- a/vm/vm_jit.go
+++ b/core/vm/vm_jit.go
@@ -19,7 +19,7 @@ import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"math/big"
"unsafe"
)
diff --git a/vm/vm_jit_fake.go b/core/vm/vm_jit_fake.go
index d6b5be45b..d6b5be45b 100644
--- a/vm/vm_jit_fake.go
+++ b/core/vm/vm_jit_fake.go
diff --git a/vm/vm_test.go b/core/vm/vm_test.go
index 9bd147a72..9bd147a72 100644
--- a/vm/vm_test.go
+++ b/core/vm/vm_test.go
diff --git a/core/vm_env.go b/core/vm_env.go
index 7845d1cd9..d786844dc 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -5,8 +5,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/state"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
)
type VMEnv struct {
diff --git a/eth/backend.go b/eth/backend.go
index 4e60e16f2..ded3f0021 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -21,7 +21,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/whisper"
)
diff --git a/event/filter/eth_filter.go b/event/filter/eth_filter.go
index 1abd48389..dc032b5c2 100644
--- a/event/filter/eth_filter.go
+++ b/event/filter/eth_filter.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type FilterManager struct {
diff --git a/miner/remote_agent.go b/miner/remote_agent.go
index 8ea164f34..3911ac61e 100644
--- a/miner/remote_agent.go
+++ b/miner/remote_agent.go
@@ -17,7 +17,6 @@ type RemoteAgent struct {
func NewRemoteAgent() *RemoteAgent {
agent := &RemoteAgent{}
- go agent.run()
return agent
}
@@ -33,6 +32,7 @@ func (a *RemoteAgent) SetWorkCh(returnCh chan<- Work) {
func (a *RemoteAgent) Start() {
a.quit = make(chan struct{})
a.workCh = make(chan *types.Block, 1)
+ go a.run()
}
func (a *RemoteAgent) Stop() {
diff --git a/miner/worker.go b/miner/worker.go
index 4a52a40fe..e21765f9d 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -13,7 +13,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"gopkg.in/fatih/set.v0"
)
@@ -24,7 +24,7 @@ type environment struct {
state *state.StateDB
coinbase *state.StateObject
block *types.Block
- ancestors *set.Set
+ family *set.Set
uncles *set.Set
}
@@ -34,13 +34,10 @@ func env(block *types.Block, eth core.Backend) *environment {
totalUsedGas: new(big.Int),
state: state,
block: block,
- ancestors: set.New(),
+ family: set.New(),
uncles: set.New(),
coinbase: state.GetOrNewStateObject(block.Coinbase()),
}
- for _, ancestor := range eth.ChainManager().GetAncestors(block, 7) {
- env.ancestors.Add(ancestor.Hash())
- }
return env
}
@@ -75,17 +72,21 @@ type worker struct {
current *environment
+ uncleMu sync.Mutex
+ possibleUncles map[common.Hash]*types.Block
+
mining bool
}
func newWorker(coinbase common.Address, eth core.Backend) *worker {
return &worker{
- eth: eth,
- mux: eth.EventMux(),
- recv: make(chan Work),
- chain: eth.ChainManager(),
- proc: eth.BlockProcessor(),
- coinbase: coinbase,
+ eth: eth,
+ mux: eth.EventMux(),
+ recv: make(chan Work),
+ chain: eth.ChainManager(),
+ proc: eth.BlockProcessor(),
+ possibleUncles: make(map[common.Hash]*types.Block),
+ coinbase: coinbase,
}
}
@@ -115,7 +116,7 @@ func (self *worker) register(agent Agent) {
}
func (self *worker) update() {
- events := self.mux.Subscribe(core.ChainHeadEvent{}, core.NewMinedBlockEvent{})
+ events := self.mux.Subscribe(core.ChainHeadEvent{}, core.NewMinedBlockEvent{}, core.ChainSideEvent{})
timer := time.NewTicker(2 * time.Second)
@@ -130,6 +131,10 @@ out:
}
case core.NewMinedBlockEvent:
self.commitNewWork()
+ case core.ChainSideEvent:
+ self.uncleMu.Lock()
+ self.possibleUncles[ev.Block.Hash()] = ev.Block
+ self.uncleMu.Unlock()
}
case <-self.quit:
// stop all agents
@@ -145,6 +150,9 @@ out:
events.Unsubscribe()
}
+func (self *worker) addUncle(uncle *types.Block) {
+}
+
func (self *worker) wait() {
for {
for work := range self.recv {
@@ -162,6 +170,10 @@ func (self *worker) wait() {
})
if err := self.chain.InsertChain(types.Blocks{self.current.block}); err == nil {
+ for _, uncle := range self.current.block.Uncles() {
+ delete(self.possibleUncles, uncle.Hash())
+ }
+
self.mux.Post(core.NewMinedBlockEvent{self.current.block})
} else {
self.commitNewWork()
@@ -191,15 +203,21 @@ func (self *worker) commitNewWork() {
block := self.chain.NewBlock(self.coinbase)
self.current = env(block, self.eth)
+ for _, ancestor := range self.chain.GetAncestors(block, 7) {
+ self.current.family.Add(ancestor.Hash())
+ }
+
parent := self.chain.GetBlock(self.current.block.ParentHash())
self.current.coinbase.SetGasPool(core.CalcGasLimit(parent, self.current.block))
transactions := self.eth.TxPool().GetTransactions()
sort.Sort(types.TxByNonce{transactions})
- minerlogger.Infof("committing new work with %d txs\n", len(transactions))
// Keep track of transactions which return errors so they can be removed
- var remove types.Transactions
+ var (
+ remove types.Transactions
+ tcount = 0
+ )
gasLimit:
for i, tx := range transactions {
err := self.commitTransaction(tx)
@@ -217,10 +235,30 @@ gasLimit:
minerlogger.Infof("Gas limit reached for block. %d TXs included in this block\n", i)
// Break on gas limit
break gasLimit
+ default:
+ tcount++
}
}
self.eth.TxPool().RemoveSet(remove)
+ var uncles []*types.Header
+ for hash, uncle := range self.possibleUncles {
+ if len(uncles) == 2 {
+ break
+ }
+
+ if err := self.commitUncle(uncle.Header()); err != nil {
+ minerlogger.Infof("Bad uncle found and will be removed (%x)\n", hash[:4])
+ minerlogger.Debugln(uncle)
+ } else {
+ minerlogger.Infof("commiting %x as uncle\n", hash[:4])
+ uncles = append(uncles, uncle.Header())
+ }
+ }
+ minerlogger.Infof("commit new work with %d txs & %d uncles\n", tcount, len(uncles))
+
+ self.current.block.SetUncles(uncles)
+
self.current.state.AddBalance(self.coinbase, core.BlockReward)
self.current.state.Update(common.Big0)
@@ -240,18 +278,16 @@ func (self *worker) commitUncle(uncle *types.Header) error {
}
self.current.uncles.Add(uncle.Hash())
- if !self.current.ancestors.Has(uncle.ParentHash) {
+ if !self.current.family.Has(uncle.ParentHash) {
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
- if !self.pow.Verify(types.NewBlockWithHeader(uncle)) {
- return core.ValidationError("Uncle's nonce is invalid (= %x)", uncle.Nonce)
+ if self.current.family.Has(uncle.Hash()) {
+ return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash()))
}
- uncleAccount := self.current.state.GetAccount(uncle.Coinbase)
- uncleAccount.AddBalance(uncleReward)
-
- self.current.coinbase.AddBalance(uncleReward)
+ self.current.state.AddBalance(uncle.Coinbase, uncleReward)
+ self.current.state.AddBalance(self.coinbase, inclusionReward)
return nil
}
diff --git a/rpc/api.go b/rpc/api.go
index 427032995..19bd9b707 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -21,7 +21,10 @@ type EthereumApi struct {
func NewEthereumApi(xeth *xeth.XEth, dataDir string) *EthereumApi {
// What about when dataDir is empty?
- db, _ := ethdb.NewLDBDatabase(path.Join(dataDir, "dapps"))
+ db, err := ethdb.NewLDBDatabase(path.Join(dataDir, "dapps"))
+ if err != nil {
+ panic(err)
+ }
api := &EthereumApi{
eth: xeth,
db: db,
@@ -41,6 +44,10 @@ func (api *EthereumApi) xethAtStateNum(num int64) *xeth.XEth {
return api.xeth().AtStateNum(num)
}
+func (api *EthereumApi) Close() {
+ api.db.Close()
+}
+
func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
// Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
rpclogger.Debugf("%s %s", req.Method, req.Params)
@@ -361,7 +368,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
- api.db.Put([]byte(args.Database+args.Key), []byte(args.Value))
+ api.db.Put([]byte(args.Database+args.Key), args.Value)
*reply = true
case "db_getString":
args := new(DbArgs)
@@ -375,8 +382,30 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
res, _ := api.db.Get([]byte(args.Database + args.Key))
*reply = string(res)
- case "db_putHex", "db_getHex":
- return NewNotImplementedError(req.Method)
+ case "db_putHex":
+ args := new(DbHexArgs)
+ if err := json.Unmarshal(req.Params, &args); err != nil {
+ return err
+ }
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ api.db.Put([]byte(args.Database+args.Key), args.Value)
+ *reply = true
+ case "db_getHex":
+ args := new(DbHexArgs)
+ if err := json.Unmarshal(req.Params, &args); err != nil {
+ return err
+ }
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ res, _ := api.db.Get([]byte(args.Database + args.Key))
+ *reply = common.ToHex(res)
case "shh_post":
args := new(WhisperMessageArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
diff --git a/rpc/api_test.go b/rpc/api_test.go
index 727ade007..a00c2f3f1 100644
--- a/rpc/api_test.go
+++ b/rpc/api_test.go
@@ -5,6 +5,8 @@ import (
// "sync"
"testing"
// "time"
+
+ "github.com/ethereum/go-ethereum/xeth"
)
func TestWeb3Sha3(t *testing.T) {
@@ -24,6 +26,50 @@ func TestWeb3Sha3(t *testing.T) {
}
}
+func TestDbStr(t *testing.T) {
+ jsonput := `{"jsonrpc":"2.0","method":"db_putString","params":["testDB","myKey","myString"],"id":64}`
+ jsonget := `{"jsonrpc":"2.0","method":"db_getString","params":["testDB","myKey"],"id":64}`
+ expected := "myString"
+
+ xeth := &xeth.XEth{}
+ api := NewEthereumApi(xeth, "")
+ defer api.db.Close()
+ var response interface{}
+
+ var req RpcRequest
+ json.Unmarshal([]byte(jsonput), &req)
+ _ = api.GetRequestReply(&req, &response)
+
+ json.Unmarshal([]byte(jsonget), &req)
+ _ = api.GetRequestReply(&req, &response)
+
+ if response.(string) != expected {
+ t.Errorf("Expected %s got %s", expected, response)
+ }
+}
+
+func TestDbHexStr(t *testing.T) {
+ jsonput := `{"jsonrpc":"2.0","method":"db_putHex","params":["testDB","beefKey","0xbeef"],"id":64}`
+ jsonget := `{"jsonrpc":"2.0","method":"db_getHex","params":["testDB","beefKey"],"id":64}`
+ expected := "0xbeef"
+
+ xeth := &xeth.XEth{}
+ api := NewEthereumApi(xeth, "")
+ defer api.db.Close()
+ var response interface{}
+
+ var req RpcRequest
+ json.Unmarshal([]byte(jsonput), &req)
+ _ = api.GetRequestReply(&req, &response)
+
+ json.Unmarshal([]byte(jsonget), &req)
+ _ = api.GetRequestReply(&req, &response)
+
+ if response.(string) != expected {
+ t.Errorf("Expected %s got %s", expected, response)
+ }
+}
+
// func TestFilterClose(t *testing.T) {
// t.Skip()
// api := &EthereumApi{
diff --git a/rpc/args.go b/rpc/args.go
index 504e67c07..5b655024c 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
)
-func blockAge(raw interface{}, number *int64) (err error) {
+func blockHeight(raw interface{}, number *int64) (err error) {
// Parse as integer
num, ok := raw.(float64)
if ok {
@@ -26,7 +26,7 @@ func blockAge(raw interface{}, number *int64) (err error) {
case "latest":
*number = -1
case "pending":
- *number = 0
+ *number = -2
default:
*number = common.String2Big(str).Int64()
}
@@ -137,7 +137,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return NewDecodeParamError(err.Error())
}
- if err := blockAge(raw, &args.BlockNumber); err != nil {
+ if err := blockHeight(raw, &args.BlockNumber); err != nil {
return err
}
}
@@ -174,7 +174,7 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
args.Address = addstr
if len(obj) > 1 {
- if err := blockAge(obj[1], &args.BlockNumber); err != nil {
+ if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
return err
}
}
@@ -218,7 +218,7 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
args.Key = keystr
if len(obj) > 2 {
- if err := blockAge(obj[2], &args.BlockNumber); err != nil {
+ if err := blockHeight(obj[2], &args.BlockNumber); err != nil {
return err
}
}
@@ -259,7 +259,7 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
args.Address = addstr
if len(obj) > 1 {
- if err := blockAge(obj[1], &args.BlockNumber); err != nil {
+ if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
return err
}
}
@@ -296,7 +296,7 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
args.Address = addstr
if len(obj) > 1 {
- if err := blockAge(obj[1], &args.BlockNumber); err != nil {
+ if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
return err
}
}
@@ -333,7 +333,7 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
args.Address = addstr
if len(obj) > 1 {
- if err := blockAge(obj[1], &args.BlockNumber); err != nil {
+ if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
return err
}
}
@@ -467,7 +467,7 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
switch fromstr {
case "latest":
- args.Earliest = 0
+ args.Earliest = -1
default:
args.Earliest = int64(common.Big(obj[0].FromBlock.(string)).Int64())
}
@@ -479,9 +479,9 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
switch tostr {
case "latest":
- args.Latest = 0
- case "pending":
args.Latest = -1
+ case "pending":
+ args.Latest = -2
default:
args.Latest = int64(common.Big(obj[0].ToBlock.(string)).Int64())
}
@@ -497,24 +497,39 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
type DbArgs struct {
Database string
Key string
- Value string
+ Value []byte
}
func (args *DbArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
- r := bytes.NewReader(b)
- if err := json.NewDecoder(r).Decode(&obj); err != nil {
+ if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
if len(obj) < 2 {
return NewInsufficientParamsError(len(obj), 2)
}
- args.Database = obj[0].(string)
- args.Key = obj[1].(string)
+
+ var objstr string
+ var ok bool
+
+ if objstr, ok = obj[0].(string); !ok {
+ return NewDecodeParamError("Database is not a string")
+ }
+ args.Database = objstr
+
+ if objstr, ok = obj[1].(string); !ok {
+ return NewDecodeParamError("Key is not a string")
+ }
+ args.Key = objstr
if len(obj) > 2 {
- args.Value = obj[2].(string)
+ objstr, ok = obj[2].(string)
+ if !ok {
+ return NewDecodeParamError("Value is not a string")
+ }
+
+ args.Value = []byte(objstr)
}
return nil
@@ -530,6 +545,57 @@ func (a *DbArgs) requirements() error {
return nil
}
+type DbHexArgs struct {
+ Database string
+ Key string
+ Value []byte
+}
+
+func (args *DbHexArgs) UnmarshalJSON(b []byte) (err error) {
+ var obj []interface{}
+ if err := json.Unmarshal(b, &obj); err != nil {
+ return NewDecodeParamError(err.Error())
+ }
+
+ if len(obj) < 2 {
+ return NewInsufficientParamsError(len(obj), 2)
+ }
+
+ var objstr string
+ var ok bool
+
+ if objstr, ok = obj[0].(string); !ok {
+ return NewDecodeParamError("Database is not a string")
+ }
+ args.Database = objstr
+
+ if objstr, ok = obj[1].(string); !ok {
+ return NewDecodeParamError("Key is not a string")
+ }
+ args.Key = objstr
+
+ if len(obj) > 2 {
+ objstr, ok = obj[2].(string)
+ if !ok {
+ return NewDecodeParamError("Value is not a string")
+ }
+
+ args.Value = common.FromHex(objstr)
+ }
+
+ return nil
+}
+
+func (a *DbHexArgs) requirements() error {
+ if len(a.Database) == 0 {
+ return NewValidationError("Database", "cannot be blank")
+ }
+ if len(a.Key) == 0 {
+ return NewValidationError("Key", "cannot be blank")
+ }
+ return nil
+}
+
type WhisperMessageArgs struct {
Payload string
To string
@@ -709,8 +775,7 @@ func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
return NewDecodeParamError("Nonce is not a string")
}
- args.Nonce = common.BytesToNumber(common.Hex2Bytes(objstr))
-
+ args.Nonce = common.String2Big(objstr).Uint64()
if objstr, ok = obj[1].(string); !ok {
return NewDecodeParamError("Header is not a string")
}
diff --git a/rpc/args_test.go b/rpc/args_test.go
index cfdd278b8..5cbafd4b2 100644
--- a/rpc/args_test.go
+++ b/rpc/args_test.go
@@ -5,6 +5,8 @@ import (
"encoding/json"
"math/big"
"testing"
+
+ "github.com/ethereum/go-ethereum/common"
)
func TestSha3(t *testing.T) {
@@ -440,8 +442,8 @@ func TestBlockFilterArgsWords(t *testing.T) {
"toBlock": "pending"
}]`
expected := new(BlockFilterArgs)
- expected.Earliest = 0
- expected.Latest = -1
+ expected.Earliest = -1
+ expected.Latest = -2
args := new(BlockFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {
@@ -485,11 +487,11 @@ func TestBlockFilterArgsEmptyArgs(t *testing.T) {
}
func TestDbArgs(t *testing.T) {
- input := `["0x74657374","0x6b6579","0x6d79537472696e67"]`
+ input := `["testDB","myKey","0xbeef"]`
expected := new(DbArgs)
- expected.Database = "0x74657374"
- expected.Key = "0x6b6579"
- expected.Value = "0x6d79537472696e67"
+ expected.Database = "testDB"
+ expected.Key = "myKey"
+ expected.Value = []byte("0xbeef")
args := new(DbArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {
@@ -508,7 +510,36 @@ func TestDbArgs(t *testing.T) {
t.Errorf("Key shoud be %#v but is %#v", expected.Key, args.Key)
}
- if expected.Value != args.Value {
+ if bytes.Compare(expected.Value, args.Value) != 0 {
+ t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
+ }
+}
+
+func TestDbHexArgs(t *testing.T) {
+ input := `["testDB","myKey","0xbeef"]`
+ expected := new(DbHexArgs)
+ expected.Database = "testDB"
+ expected.Key = "myKey"
+ expected.Value = []byte{0xbe, 0xef}
+
+ args := new(DbHexArgs)
+ if err := json.Unmarshal([]byte(input), &args); err != nil {
+ t.Error(err)
+ }
+
+ if err := args.requirements(); err != nil {
+ t.Error(err)
+ }
+
+ if expected.Database != args.Database {
+ t.Errorf("Database shoud be %#v but is %#v", expected.Database, args.Database)
+ }
+
+ if expected.Key != args.Key {
+ t.Errorf("Key shoud be %#v but is %#v", expected.Key, args.Key)
+ }
+
+ if bytes.Compare(expected.Value, args.Value) != 0 {
t.Errorf("Value shoud be %#v but is %#v", expected.Value, args.Value)
}
}
@@ -622,6 +653,10 @@ func TestFilterStringArgs(t *testing.T) {
t.Error(err)
}
+ if err := args.requirements(); err != nil {
+ t.Error(err)
+ }
+
if expected.Word != args.Word {
t.Errorf("Word shoud be %#v but is %#v", expected.Word, args.Word)
}
@@ -691,3 +726,28 @@ func TestHashIndexArgs(t *testing.T) {
t.Errorf("Index shoud be %#v but is %#v", expected.Index, args.Index)
}
}
+
+func TestSubmitWorkArgs(t *testing.T) {
+ input := `["0x0000000000000001", "0x1234567890abcdef1234567890abcdef", "0xD1GE5700000000000000000000000000"]`
+ expected := new(SubmitWorkArgs)
+ expected.Nonce = 1
+ expected.Header = common.HexToHash("0x1234567890abcdef1234567890abcdef")
+ expected.Digest = common.HexToHash("0xD1GE5700000000000000000000000000")
+
+ args := new(SubmitWorkArgs)
+ if err := json.Unmarshal([]byte(input), &args); err != nil {
+ t.Error(err)
+ }
+
+ if expected.Nonce != args.Nonce {
+ t.Errorf("Nonce shoud be %d but is %d", expected.Nonce, args.Nonce)
+ }
+
+ if expected.Header != args.Header {
+ t.Errorf("Header shoud be %#v but is %#v", expected.Header, args.Header)
+ }
+
+ if expected.Digest != args.Digest {
+ t.Errorf("Digest shoud be %#v but is %#v", expected.Digest, args.Digest)
+ }
+}
diff --git a/rpc/responses.go b/rpc/responses.go
index 1ec5f08eb..993f467ea 100644
--- a/rpc/responses.go
+++ b/rpc/responses.go
@@ -7,7 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type BlockRes struct {
diff --git a/tests/blocktest.go b/tests/blocktest.go
index 44b459c8d..34bd69ac8 100644
--- a/tests/blocktest.go
+++ b/tests/blocktest.go
@@ -15,15 +15,15 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
// Block Test JSON Format
-
type btJSON struct {
Blocks []btBlock
GenesisBlockHeader btHeader
Pre map[string]btAccount
+ PostState map[string]btAccount
}
type btAccount struct {
@@ -97,7 +97,7 @@ func LoadBlockTests(file string) (map[string]*BlockTest, error) {
// InsertPreState populates the given database with the genesis
// accounts defined by the test.
-func (t *BlockTest) InsertPreState(db common.Database) error {
+func (t *BlockTest) InsertPreState(db common.Database) (*state.StateDB, error) {
statedb := state.New(common.Hash{}, db)
for addrString, acct := range t.preAccounts {
// XXX: is is worth it checking for errors here?
@@ -119,8 +119,33 @@ func (t *BlockTest) InsertPreState(db common.Database) error {
// sync trie to disk
statedb.Sync()
- if t.Genesis.Root() != statedb.Root() {
- return errors.New("computed state root does not match genesis block")
+ if !bytes.Equal(t.Genesis.Root().Bytes(), statedb.Root().Bytes()) {
+ return nil, errors.New("computed state root does not match genesis block")
+ }
+ return statedb, nil
+}
+
+func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
+ for addrString, acct := range t.preAccounts {
+ // XXX: is is worth it checking for errors here?
+ addr, _ := hex.DecodeString(addrString)
+ code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x"))
+ balance, _ := new(big.Int).SetString(acct.Balance, 0)
+ nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
+
+ // address is indirectly verified by the other fields, as it's the db key
+ code2 := statedb.GetCode(common.BytesToAddress(addr))
+ balance2 := statedb.GetBalance(common.BytesToAddress(addr))
+ nonce2 := statedb.GetNonce(common.BytesToAddress(addr))
+ if !bytes.Equal(code2, code) {
+ return fmt.Errorf("account code mismatch, addr, found, expected: ", addrString, hex.EncodeToString(code2), hex.EncodeToString(code))
+ }
+ if balance2.Cmp(balance) != 0 {
+ return fmt.Errorf("account balance mismatch, addr, found, expected: ", addrString, balance2, balance)
+ }
+ if nonce2 != nonce {
+ return fmt.Errorf("account nonce mismatch, addr, found, expected: ", addrString, nonce2, nonce)
+ }
}
return nil
}
diff --git a/tests/helper/vm.go b/tests/helper/vm.go
index 44c108870..68ae8e97b 100644
--- a/tests/helper/vm.go
+++ b/tests/helper/vm.go
@@ -7,8 +7,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/state"
- "github.com/ethereum/go-ethereum/vm"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
)
type Env struct {
diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go
index 68600d304..123e8ccb5 100644
--- a/tests/vm/gh_test.go
+++ b/tests/vm/gh_test.go
@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/tests/helper"
)
diff --git a/vm/.ethtest b/vm/.ethtest
deleted file mode 100644
index e69de29bb..000000000
--- a/vm/.ethtest
+++ /dev/null
diff --git a/xeth/state.go b/xeth/state.go
index f645a9cac..b0f2ce019 100644
--- a/xeth/state.go
+++ b/xeth/state.go
@@ -2,7 +2,7 @@ package xeth
import (
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type State struct {
diff --git a/xeth/types.go b/xeth/types.go
index b4ba7bab0..09d0dc714 100644
--- a/xeth/types.go
+++ b/xeth/types.go
@@ -11,7 +11,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
)
type Object struct {
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 23e523980..02a691ffb 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -19,7 +19,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/whisper"
)
@@ -176,9 +176,12 @@ func (self *XEth) AtStateNum(num int64) *XEth {
chain := self.Backend().ChainManager()
var block *types.Block
+ // -1 generally means "latest"
+ // -2 means "pending", which has no blocknum
if num < 0 {
- num = chain.CurrentBlock().Number().Int64() + num + 1
+ num = chain.CurrentBlock().Number().Int64()
}
+
block = chain.GetBlockByNumber(uint64(num))
var st *state.StateDB
@@ -229,6 +232,11 @@ func (self *XEth) EthTransactionByHash(hash string) *types.Transaction {
}
func (self *XEth) BlockByNumber(num int64) *Block {
+ if num == -2 {
+ // "pending" is non-existant
+ return &Block{}
+ }
+
if num == -1 {
return NewBlock(self.chainManager.CurrentBlock())
}
@@ -237,6 +245,11 @@ func (self *XEth) BlockByNumber(num int64) *Block {
}
func (self *XEth) EthBlockByNumber(num int64) *types.Block {
+ if num == -2 {
+ // "pending" is non-existant
+ return &types.Block{}
+ }
+
if num == -1 {
return self.chainManager.CurrentBlock()
}