Prechádzať zdrojové kódy

cmd/core,xeth: removed unneeded states & added batch writes

Jeffrey Wilcke 10 rokov pred
rodič
commit
8fc9830971
5 zmenil súbory, kde vykonal 120 pridanie a 59 odobranie
  1. 81 31
      cmd/evm/main.go
  2. 0 22
      core/chain_manager.go
  3. 0 1
      core/chain_manager_test.go
  4. 38 4
      core/transaction_util.go
  5. 1 1
      xeth/xeth.go

+ 81 - 31
cmd/evm/main.go

@@ -18,79 +18,129 @@
 package main
 
 import (
-	"flag"
 	"fmt"
-	"log"
 	"math/big"
 	"os"
 	"runtime"
 	"time"
 
+	"github.com/codegangsta/cli"
+	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/ethdb"
-	"github.com/ethereum/go-ethereum/logger"
 )
 
 var (
-	code     = flag.String("code", "", "evm code")
-	loglevel = flag.Int("log", 4, "log level")
-	gas      = flag.String("gas", "1000000000", "gas amount")
-	price    = flag.String("price", "0", "gas price")
-	value    = flag.String("value", "0", "tx value")
-	dump     = flag.Bool("dump", false, "dump state after run")
-	data     = flag.String("data", "", "data")
+	app       *cli.App
+	DebugFlag = cli.BoolFlag{
+		Name:  "debug",
+		Usage: "output full trace logs",
+	}
+	CodeFlag = cli.StringFlag{
+		Name:  "code",
+		Usage: "EVM code",
+	}
+	GasFlag = cli.StringFlag{
+		Name:  "gas",
+		Usage: "gas limit for the evm",
+		Value: "10000000000",
+	}
+	PriceFlag = cli.StringFlag{
+		Name:  "price",
+		Usage: "price set for the evm",
+		Value: "0",
+	}
+	ValueFlag = cli.StringFlag{
+		Name:  "value",
+		Usage: "value set for the evm",
+		Value: "0",
+	}
+	DumpFlag = cli.BoolFlag{
+		Name:  "dump",
+		Usage: "dumps the state after the run",
+	}
+	InputFlag = cli.StringFlag{
+		Name:  "input",
+		Usage: "input for the EVM",
+	}
+	SysStatFlag = cli.BoolFlag{
+		Name:  "sysstat",
+		Usage: "display system stats",
+	}
 )
 
-func perr(v ...interface{}) {
-	fmt.Println(v...)
-	//os.Exit(1)
+func init() {
+	app = utils.NewApp("0.2", "the evm command line interface")
+	app.Flags = []cli.Flag{
+		DebugFlag,
+		SysStatFlag,
+		CodeFlag,
+		GasFlag,
+		PriceFlag,
+		ValueFlag,
+		DumpFlag,
+		InputFlag,
+	}
+	app.Action = run
 }
 
-func main() {
-	flag.Parse()
-
-	logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel)))
+func run(ctx *cli.Context) {
+	vm.Debug = ctx.GlobalBool(DebugFlag.Name)
 
-	vm.Debug = true
 	db, _ := ethdb.NewMemDatabase()
 	statedb := state.New(common.Hash{}, db)
 	sender := statedb.CreateAccount(common.StringToAddress("sender"))
 	receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
-	receiver.SetCode(common.Hex2Bytes(*code))
+	receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
 
-	vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(*value))
+	vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)))
 
 	tstart := time.Now()
+	ret, e := vmenv.Call(
+		sender,
+		receiver.Address(),
+		common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)),
+		common.Big(ctx.GlobalString(GasFlag.Name)),
+		common.Big(ctx.GlobalString(PriceFlag.Name)),
+		common.Big(ctx.GlobalString(ValueFlag.Name)),
+	)
+	vmdone := time.Since(tstart)
 
-	ret, e := vmenv.Call(sender, receiver.Address(), common.Hex2Bytes(*data), common.Big(*gas), common.Big(*price), common.Big(*value))
-
-	logger.Flush()
 	if e != nil {
-		perr(e)
+		fmt.Println(e)
+		os.Exit(1)
 	}
 
-	if *dump {
+	if ctx.GlobalBool(DumpFlag.Name) {
 		fmt.Println(string(statedb.Dump()))
 	}
-
 	vm.StdErrFormat(vmenv.StructLogs())
 
-	var mem runtime.MemStats
-	runtime.ReadMemStats(&mem)
-	fmt.Printf("vm took %v\n", time.Since(tstart))
-	fmt.Printf(`alloc:      %d
+	if ctx.GlobalBool(SysStatFlag.Name) {
+		var mem runtime.MemStats
+		runtime.ReadMemStats(&mem)
+		fmt.Printf("vm took %v\n", vmdone)
+		fmt.Printf(`alloc:      %d
 tot alloc:  %d
 no. malloc: %d
 heap alloc: %d
 heap objs:  %d
 num gc:     %d
 `, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC)
+	}
 
-	fmt.Printf("%x\n", ret)
+	fmt.Printf("OUT: 0x%x\n", ret)
+}
+
+func main() {
+	if err := app.Run(os.Args); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
 }
 
 type VMEnv struct {

+ 0 - 22
core/chain_manager.go

@@ -73,9 +73,6 @@ type ChainManager struct {
 	lastBlockHash   common.Hash
 	currentGasLimit *big.Int
 
-	transState *state.StateDB
-	txState    *state.ManagedState
-
 	cache        *lru.Cache // cache is the LRU caching
 	futureBlocks *lru.Cache // future blocks are blocks added for later processing
 
@@ -128,9 +125,7 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux
 		}
 	}
 
-	bc.transState = bc.State().Copy()
 	// Take ownership of this particular state
-	bc.txState = state.ManageState(bc.State().Copy())
 
 	bc.futureBlocks, _ = lru.New(maxFutureBlocks)
 	bc.makeCache()
@@ -152,9 +147,6 @@ func (bc *ChainManager) SetHead(head *types.Block) {
 	bc.currentBlock = head
 	bc.makeCache()
 
-	statedb := state.New(head.Root(), bc.stateDb)
-	bc.txState = state.ManageState(statedb)
-	bc.transState = statedb.Copy()
 	bc.setTotalDifficulty(head.Td)
 	bc.insert(head)
 	bc.setLastState()
@@ -203,17 +195,6 @@ func (self *ChainManager) State() *state.StateDB {
 	return state.New(self.CurrentBlock().Root(), self.stateDb)
 }
 
-func (self *ChainManager) TransState() *state.StateDB {
-	self.tsmu.RLock()
-	defer self.tsmu.RUnlock()
-
-	return self.transState
-}
-
-func (self *ChainManager) setTransState(statedb *state.StateDB) {
-	self.transState = statedb
-}
-
 func (bc *ChainManager) recover() bool {
 	data, _ := bc.blockDb.Get([]byte("checkpoint"))
 	if len(data) != 0 {
@@ -529,9 +510,6 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr
 		self.insert(block)
 		self.mu.Unlock()
 
-		self.setTransState(state.New(block.Root(), self.stateDb))
-		self.txState.SetState(state.New(block.Root(), self.stateDb))
-
 		status = CanonStatTy
 	} else {
 		status = SideStatTy

+ 0 - 1
core/chain_manager_test.go

@@ -392,7 +392,6 @@ func chm(genesis *types.Block, db common.Database) *ChainManager {
 	bc.futureBlocks, _ = lru.New(100)
 	bc.processor = bproc{}
 	bc.ResetWithGenesisBlock(genesis)
-	bc.txState = state.ManageState(bc.State())
 
 	return bc
 }

+ 38 - 4
core/transaction_util.go

@@ -19,9 +19,11 @@ package core
 import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/logger/glog"
 	"github.com/ethereum/go-ethereum/rlp"
+	"github.com/syndtr/goleveldb/leveldb"
 )
 
 var (
@@ -31,13 +33,21 @@ var (
 
 // PutTransactions stores the transactions in the given database
 func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) {
+	batch := new(leveldb.Batch)
+	_, batchWrite := db.(*ethdb.LDBDatabase)
+
 	for i, tx := range block.Transactions() {
 		rlpEnc, err := rlp.EncodeToBytes(tx)
 		if err != nil {
 			glog.V(logger.Debug).Infoln("Failed encoding tx", err)
 			return
 		}
-		db.Put(tx.Hash().Bytes(), rlpEnc)
+
+		if batchWrite {
+			batch.Put(tx.Hash().Bytes(), rlpEnc)
+		} else {
+			db.Put(tx.Hash().Bytes(), rlpEnc)
+		}
 
 		var txExtra struct {
 			BlockHash  common.Hash
@@ -52,20 +62,44 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti
 			glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err)
 			return
 		}
-		db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
+
+		if batchWrite {
+			batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
+		} else {
+			db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
+		}
+	}
+
+	if db, ok := db.(*ethdb.LDBDatabase); ok {
+		if err := db.LDB().Write(batch, nil); err != nil {
+			glog.V(logger.Error).Infoln("db write err:", err)
+		}
 	}
 }
 
 // PutReceipts stores the receipts in the current database
 func PutReceipts(db common.Database, receipts types.Receipts) error {
+	batch := new(leveldb.Batch)
+	_, batchWrite := db.(*ethdb.LDBDatabase)
+
 	for _, receipt := range receipts {
 		storageReceipt := (*types.ReceiptForStorage)(receipt)
 		bytes, err := rlp.EncodeToBytes(storageReceipt)
 		if err != nil {
 			return err
 		}
-		err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
-		if err != nil {
+
+		if batchWrite {
+			batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
+		} else {
+			err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	if db, ok := db.(*ethdb.LDBDatabase); ok {
+		if err := db.LDB().Write(batch, nil); err != nil {
 			return err
 		}
 	}

+ 1 - 1
xeth/xeth.go

@@ -123,7 +123,7 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
 	if frontend == nil {
 		xeth.frontend = dummyFrontend{}
 	}
-	xeth.state = NewState(xeth, xeth.backend.ChainManager().TransState())
+	xeth.state = NewState(xeth, xeth.backend.ChainManager().State())
 
 	go xeth.start()
 	go xeth.filterManager.Start()