aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/evm/main.go112
-rw-r--r--core/chain_manager.go22
-rw-r--r--core/chain_manager_test.go1
-rw-r--r--core/transaction_util.go42
-rw-r--r--xeth/xeth.go2
5 files changed, 120 insertions, 59 deletions
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index ab4d3f82a..965994382 100644
--- a/cmd/evm/main.go
+++ b/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 {
diff --git a/core/chain_manager.go b/core/chain_manager.go
index b2fcb677c..0f008dfa7 100644
--- a/core/chain_manager.go
+++ b/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
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index d247c3e50..e2ad86942 100644
--- a/core/chain_manager_test.go
+++ b/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
}
diff --git a/core/transaction_util.go b/core/transaction_util.go
index 1020fbd6e..d4b9f53c9 100644
--- a/core/transaction_util.go
+++ b/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
}
}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 3bc22a43d..078a3fb8a 100644
--- a/xeth/xeth.go
+++ b/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()