diff options
-rw-r--r-- | cmd/disasm/main.go | 2 | ||||
-rw-r--r-- | cmd/ethereum/admin.go | 2 | ||||
-rw-r--r-- | cmd/ethereum/blocktest.go | 28 | ||||
-rw-r--r-- | cmd/ethereum/js.go | 1 | ||||
-rw-r--r-- | cmd/ethereum/main.go | 2 | ||||
-rw-r--r-- | cmd/ethtest/main.go | 6 | ||||
-rw-r--r-- | cmd/evm/main.go | 4 | ||||
-rw-r--r-- | cmd/mist/bindings.go | 2 | ||||
-rw-r--r-- | cmd/utils/flags.go | 2 | ||||
-rw-r--r-- | core/asm.go | 2 | ||||
-rw-r--r-- | core/block_cache.go | 5 | ||||
-rw-r--r-- | core/block_processor.go | 38 | ||||
-rw-r--r-- | core/chain_makers.go | 2 | ||||
-rw-r--r-- | core/chain_manager.go | 49 | ||||
-rw-r--r-- | core/error.go | 5 | ||||
-rw-r--r-- | core/events.go | 6 | ||||
-rw-r--r-- | core/execution.go | 4 | ||||
-rw-r--r-- | core/filter.go | 2 | ||||
-rw-r--r-- | core/genesis.go | 2 | ||||
-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.go | 4 | ||||
-rw-r--r-- | core/transaction_pool_test.go | 2 | ||||
-rw-r--r-- | core/types/bloom9.go | 2 | ||||
-rw-r--r-- | core/types/bloom9_test.go | 2 | ||||
-rw-r--r-- | core/types/common.go | 2 | ||||
-rw-r--r-- | core/types/receipt.go | 2 | ||||
-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.go | 4 | ||||
-rw-r--r-- | eth/backend.go | 2 | ||||
-rw-r--r-- | event/filter/eth_filter.go | 2 | ||||
-rw-r--r-- | miner/remote_agent.go | 2 | ||||
-rw-r--r-- | miner/worker.go | 80 | ||||
-rw-r--r-- | rpc/api.go | 37 | ||||
-rw-r--r-- | rpc/api_test.go | 46 | ||||
-rw-r--r-- | rpc/args.go | 103 | ||||
-rw-r--r-- | rpc/args_test.go | 74 | ||||
-rw-r--r-- | rpc/responses.go | 2 | ||||
-rw-r--r-- | tests/blocktest.go | 35 | ||||
-rw-r--r-- | tests/helper/vm.go | 4 | ||||
-rw-r--r-- | tests/vm/gh_test.go | 2 | ||||
-rw-r--r-- | vm/.ethtest | 0 | ||||
-rw-r--r-- | xeth/state.go | 2 | ||||
-rw-r--r-- | xeth/types.go | 2 | ||||
-rw-r--r-- | xeth/xeth.go | 17 |
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() } |