Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/evm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func run(ctx *cli.Context) {
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))

db, _ := ethdb.NewMemDatabase()
statedb := state.New(common.Hash{}, db)
statedb, _ := state.New(common.Hash{}, db)
sender := statedb.CreateAccount(common.StringToAddress("sender"))
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
Expand Down
10 changes: 7 additions & 3 deletions cmd/geth/blocktestcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ func runBlockTest(ctx *cli.Context) {

func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) {
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
cfg.NewDB = func(path string) (ethdb.Database, error) { return ethdb.NewMemDatabase() }
db, _ := ethdb.NewMemDatabase()
cfg.NewDB = func(path string) (ethdb.Database, error) { return db, nil }
cfg.MaxPeers = 0 // disable network
cfg.Shh = false // disable whisper
cfg.NAT = nil // disable port mapping
Expand All @@ -113,7 +114,7 @@ func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, er
// import the genesis block
ethereum.ResetWithGenesisBlock(test.Genesis)
// import pre accounts
_, err = test.InsertPreState(ethereum)
_, err = test.InsertPreState(db, cfg.AccountManager)
if err != nil {
return ethereum, fmt.Errorf("InsertPreState: %v", err)
}
Expand All @@ -123,7 +124,10 @@ func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, er
if err != nil {
return ethereum, fmt.Errorf("Block Test load error: %v", err)
}
newDB := cm.State()
newDB, err := cm.State()
if err != nil {
return ethereum, fmt.Errorf("Block Test get state error: %v", err)
}
if err := test.ValidatePostState(newDB); err != nil {
return ethereum, fmt.Errorf("post state validation failed: %v", err)
}
Expand Down
6 changes: 5 additions & 1 deletion cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ func dump(ctx *cli.Context) {
fmt.Println("{}")
utils.Fatalf("block not found")
} else {
state := state.New(block.Root(), chainDb)
state, err := state.New(block.Root(), chainDb)
if err != nil {
utils.Fatalf("could not create new state: %v", err)
return
}
fmt.Printf("%s\n", state.Dump())
}
}
Expand Down
5 changes: 4 additions & 1 deletion core/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,10 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs vm.Logs, receipts ty

func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs vm.Logs, receipts types.Receipts, err error) {
// Create a new state based on the parent's root (e.g., create copy)
state := state.New(parent.Root(), sm.chainDb)
state, err := state.New(parent.Root(), sm.chainDb)
if err != nil {
return nil, nil, err
}
header := block.Header()
uncles := block.Uncles()
txs := block.Transactions()
Expand Down
2 changes: 1 addition & 1 deletion core/block_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestNumber(t *testing.T) {
pow := ezp.New()
_, chain := proc()

statedb := state.New(chain.Genesis().Root(), chain.chainDb)
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
header := makeHeader(chain.Genesis(), statedb)
header.Number = big.NewInt(3)
err := ValidateHeader(pow, header, chain.Genesis().Header(), false, false)
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (self *BlockChain) SetProcessor(proc types.BlockProcessor) {
self.processor = proc
}

func (self *BlockChain) State() *state.StateDB {
func (self *BlockChain) State() (*state.StateDB, error) {
return state.New(self.CurrentBlock().Root(), self.chainDb)
}

Expand Down
5 changes: 4 additions & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ func (b *BlockGen) OffsetTime(seconds int64) {
// values. Inserting them into BlockChain requires use of FakePow or
// a similar non-validating proof of work implementation.
func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) []*types.Block {
statedb := state.New(parent.Root(), db)
statedb, err := state.New(parent.Root(), db)
if err != nil {
panic(err)
}
blocks := make(types.Blocks, n)
genblock := func(i int, h *types.Header) *types.Block {
b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb}
Expand Down
2 changes: 1 addition & 1 deletion core/chain_makers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func ExampleGenerateChain() {
return
}

state := chainman.State()
state, _ := chainman.State()
fmt.Printf("last block: #%d\n", chainman.CurrentBlock().Number())
fmt.Println("balance of addr1:", state.GetBalance(addr1))
fmt.Println("balance of addr2:", state.GetBalance(addr2))
Expand Down
7 changes: 4 additions & 3 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
return nil, err
}

statedb := state.New(common.Hash{}, chainDb)
// creating with empty hash always works
statedb, _ := state.New(common.Hash{}, chainDb)
for addr, account := range genesis.Alloc {
address := common.HexToAddress(addr)
statedb.AddBalance(address, common.String2Big(account.Balance))
Expand Down Expand Up @@ -115,9 +116,9 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
}

// GenesisBlockForTesting creates a block in which addr has the given wei balance.
// The state trie of the block is written to db.
// The state trie of the block is written to db. the passed db needs to contain a state root
func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
statedb := state.New(common.Hash{}, db)
statedb, _ := state.New(common.Hash{}, db)
obj := statedb.GetOrNewStateObject(addr)
obj.SetBalance(balance)
root, err := statedb.Commit()
Expand Down
2 changes: 1 addition & 1 deletion core/state/managed_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var addr = common.BytesToAddress([]byte("test"))

func create() (*ManagedState, *account) {
db, _ := ethdb.NewMemDatabase()
statedb := New(common.Hash{}, db)
statedb, _ := New(common.Hash{}, db)
ms := ManageState(statedb)
so := &StateObject{address: addr, nonce: 100}
ms.StateDB.stateObjects[addr.Str()] = so
Expand Down
6 changes: 3 additions & 3 deletions core/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ func (s *StateSuite) TestDump(c *checker.C) {

func (s *StateSuite) SetUpTest(c *checker.C) {
db, _ := ethdb.NewMemDatabase()
s.state = New(common.Hash{}, db)
s.state, _ = New(common.Hash{}, db)
}

func TestNull(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
state := New(common.Hash{}, db)
state, _ := New(common.Hash{}, db)

address := common.HexToAddress("0x823140710bf13990e4500136726d8b55")
state.CreateAccount(address)
Expand Down Expand Up @@ -122,7 +122,7 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {
// printing/logging in tests (-check.vv does not work)
func TestSnapshot2(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
state := New(common.Hash{}, db)
state, _ := New(common.Hash{}, db)

stateobjaddr0 := toAddr([]byte("so0"))
stateobjaddr1 := toAddr([]byte("so1"))
Expand Down
10 changes: 5 additions & 5 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,19 @@ type StateDB struct {
}

// Create a new state from a given trie
func New(root common.Hash, db ethdb.Database) *StateDB {
func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
tr, err := trie.NewSecure(root, db)
if err != nil {
// TODO: bubble this up
tr, _ = trie.NewSecure(common.Hash{}, db)
glog.Errorf("can't create state trie with root %x: %v", root[:], err)
return nil, err
}
return &StateDB{
db: db,
trie: tr,
stateObjects: make(map[string]*StateObject),
refund: new(big.Int),
logs: make(map[common.Hash]vm.Logs),
}
}, nil
}

func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
Expand Down Expand Up @@ -297,7 +296,8 @@ func (self *StateDB) CreateAccount(addr common.Address) vm.Account {
//

func (self *StateDB) Copy() *StateDB {
state := New(common.Hash{}, self.db)
// ignore error - we assume state-to-be-copied always exists
state, _ := New(common.Hash{}, self.db)
state.trie = self.trie
for k, stateObject := range self.stateObjects {
state.stateObjects[k] = stateObject.Copy()
Expand Down
51 changes: 41 additions & 10 deletions core/transaction_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const (
maxQueued = 64 // max limit of queued txs per address
)

type stateFn func() *state.StateDB
type stateFn func() (*state.StateDB, error)

// TxPool contains all currently known transactions. Transactions
// enter the pool when they are received from the network or submitted
Expand Down Expand Up @@ -80,7 +80,7 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
currentState: currentStateFn,
gasLimit: gasLimitFn,
minGasPrice: new(big.Int),
pendingState: state.ManageState(currentStateFn()),
pendingState: nil,
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
}
go pool.eventLoop()
Expand Down Expand Up @@ -109,7 +109,17 @@ func (pool *TxPool) eventLoop() {
}

func (pool *TxPool) resetState() {
pool.pendingState = state.ManageState(pool.currentState())
currentState, err := pool.currentState()
if err != nil {
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
return
}
managedState := state.ManageState(currentState)
if err != nil {
glog.V(logger.Info).Infoln("failed to get managed state: %v", err)
return
}
pool.pendingState = managedState

// validate the pool of pending transactions, this will remove
// any transactions that have been included in the block or
Expand Down Expand Up @@ -180,12 +190,16 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {

// Make sure the account exist. Non existent accounts
// haven't got funds and well therefor never pass.
if !pool.currentState().HasAccount(from) {
currentState, err := pool.currentState()
if err != nil {
return err
}
if !currentState.HasAccount(from) {
return ErrNonExistentAccount
}

// Last but not least check for nonce errors
if pool.currentState().GetNonce(from) > tx.Nonce() {
if currentState.GetNonce(from) > tx.Nonce() {
return ErrNonce
}

Expand All @@ -204,7 +218,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {

// Transactor should have enough funds to cover the costs
// cost == V + GP * GL
if pool.currentState().GetBalance(from).Cmp(tx.Cost()) < 0 {
if currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
return ErrInsufficientFunds
}

Expand Down Expand Up @@ -257,6 +271,11 @@ func (self *TxPool) queueTx(hash common.Hash, tx *types.Transaction) {

// addTx will add a transaction to the pending (processable queue) list of transactions
func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Transaction) {
// init delayed since tx pool could have been started before any state sync
if pool.pendingState == nil {
pool.resetState()
}

if _, ok := pool.pending[hash]; !ok {
pool.pending[hash] = tx

Expand Down Expand Up @@ -382,14 +401,22 @@ func (pool *TxPool) RemoveTx(hash common.Hash) {

// checkQueue moves transactions that have become processable to main pool.
func (pool *TxPool) checkQueue() {
state := pool.pendingState
// init delayed since tx pool could have been started before any state sync
if pool.pendingState == nil {
pool.resetState()
}

var addq txQueue
for address, txs := range pool.queue {
// guessed nonce is the nonce currently kept by the tx pool (pending state)
guessedNonce := state.GetNonce(address)
guessedNonce := pool.pendingState.GetNonce(address)
// true nonce is the nonce known by the last state
trueNonce := pool.currentState().GetNonce(address)
currentState, err := pool.currentState()
if err != nil {
glog.Errorf("could not get current state: %v", err)
return
}
trueNonce := currentState.GetNonce(address)
addq := addq[:0]
for hash, tx := range txs {
if tx.Nonce() < trueNonce {
Expand Down Expand Up @@ -434,7 +461,11 @@ func (pool *TxPool) checkQueue() {

// validatePool removes invalid and processed transactions from the main pool.
func (pool *TxPool) validatePool() {
state := pool.currentState()
state, err := pool.currentState()
if err != nil {
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
return
}
for hash, tx := range pool.pending {
from, _ := tx.From() // err already checked
// perform light nonce validation
Expand Down
Loading