diff options
author | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-07-07 21:12:56 +0800 |
---|---|---|
committer | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-07-07 21:12:56 +0800 |
commit | 193c62fdba3bb5c40daad6652c18d81d43518235 (patch) | |
tree | 4b77244b1ce72160a1434036977c7a473781665c /core | |
parent | a2ce7b99501b3273b4cee65cd6784c7d1c4645f7 (diff) | |
parent | d673c34c8d4ae83a3765ed44ae9d0fb7ce1aa3c9 (diff) | |
download | go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.tar go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.tar.gz go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.tar.bz2 go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.tar.lz go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.tar.xz go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.tar.zst go-tangerine-193c62fdba3bb5c40daad6652c18d81d43518235.zip |
Merge branch 'release/0.9.36'
Diffstat (limited to 'core')
63 files changed, 1506 insertions, 368 deletions
diff --git a/core/asm.go b/core/asm.go index f40c07904..071663992 100644 --- a/core/asm.go +++ b/core/asm.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( diff --git a/core/bad_block.go b/core/bad_block.go new file mode 100644 index 000000000..55c114645 --- /dev/null +++ b/core/bad_block.go @@ -0,0 +1,72 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +package core + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" + "github.com/ethereum/go-ethereum/rlp" +) + +// DisabledBadBlockReporting can be set to prevent blocks being reported. +var DisableBadBlockReporting = true + +// ReportBlock reports the block to the block reporting tool found at +// badblocks.ethdev.com +func ReportBlock(block *types.Block, err error) { + if DisableBadBlockReporting { + return + } + + const url = "https://badblocks.ethdev.com" + + blockRlp, _ := rlp.EncodeToBytes(block) + data := map[string]interface{}{ + "block": common.Bytes2Hex(blockRlp), + "errortype": err.Error(), + "hints": map[string]interface{}{ + "receipts": "NYI", + "vmtrace": "NYI", + }, + } + jsonStr, _ := json.Marshal(map[string]interface{}{"method": "eth_badBlock", "params": []interface{}{data}, "id": "1", "jsonrpc": "2.0"}) + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + glog.V(logger.Error).Infoln("POST err:", err) + return + } + defer resp.Body.Close() + + if glog.V(logger.Debug) { + glog.Infoln("response Status:", resp.Status) + glog.Infoln("response Headers:", resp.Header) + body, _ := ioutil.ReadAll(resp.Body) + glog.Infoln("response Body:", string(body)) + } +} diff --git a/core/bench_test.go b/core/bench_test.go index 6d851febd..645df48c2 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -152,7 +168,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Time the insertion of the new chain. // State and blocks are stored in the same DB. evmux := new(event.TypeMux) - chainman, _ := NewChainManager(genesis, db, db, FakePow{}, evmux) + chainman, _ := NewChainManager(genesis, db, db, db, FakePow{}, evmux) chainman.SetProcessor(NewBlockProcessor(db, db, FakePow{}, chainman, evmux)) defer chainman.Stop() b.ReportAllocs() diff --git a/core/block_cache.go b/core/block_cache.go index 0c747d37c..655f6c24b 100644 --- a/core/block_cache.go +++ b/core/block_cache.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( diff --git a/core/block_cache_test.go b/core/block_cache_test.go index 80d118599..abea0a654 100644 --- a/core/block_cache_test.go +++ b/core/block_cache_test.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( diff --git a/core/block_processor.go b/core/block_processor.go index 22d4c7c27..e912c0b6e 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -9,12 +25,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/pow" - "github.com/ethereum/go-ethereum/rlp" "gopkg.in/fatih/set.v0" ) @@ -24,8 +40,6 @@ const ( BlockChainVersion = 3 ) -var receiptsPre = []byte("receipts-") - type BlockProcessor struct { db common.Database extraDb common.Database @@ -74,15 +88,22 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated cb := statedb.GetStateObject(coinbase.Address()) _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb) - if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { + if err != nil { return nil, nil, err } // Update the state with pending changes - statedb.Update() + statedb.SyncIntermediate() usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas) + receipt.TxHash = tx.Hash() + receipt.GasUsed = new(big.Int).Set(gas) + if MessageCreatesContract(tx) { + from, _ := tx.From() + receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) + } + logs := statedb.GetLogs(tx.Hash()) receipt.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) @@ -114,7 +135,7 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state statedb.StartRecord(tx.Hash(), block.Hash(), i) receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, header, tx, totalUsedGas, transientProcess) - if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { + if err != nil { return nil, err } @@ -151,7 +172,7 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err errch := make(chan bool) go func() { errch <- sm.Pow.Verify(block) }() - logs, err = sm.processWithParent(block, parent) + logs, _, err = sm.processWithParent(block, parent) if !<-errch { return nil, ValidationError("Block's nonce is invalid (= %x)", block.Nonce) } @@ -162,23 +183,23 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err // Process block will attempt to process the given block's transactions and applies them // on top of the block's parent state (given it exists) and will return wether it was // successful or not. -func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err error) { +func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, receipts types.Receipts, err error) { // Processing a blocks may never happen simultaneously sm.mutex.Lock() defer sm.mutex.Unlock() if sm.bc.HasBlock(block.Hash()) { - return nil, &KnownBlockError{block.Number(), block.Hash()} + return nil, nil, &KnownBlockError{block.Number(), block.Hash()} } if !sm.bc.HasBlock(block.ParentHash()) { - return nil, ParentError(block.ParentHash()) + return nil, nil, ParentError(block.ParentHash()) } parent := sm.bc.GetBlock(block.ParentHash()) return sm.processWithParent(block, parent) } -func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) { +func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.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.db) header := block.Header() @@ -192,10 +213,10 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st // There can be at most two uncles if len(uncles) > 2 { - return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles)) + return nil, nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles)) } - receipts, err := sm.TransitionState(state, parent, block, false) + receipts, err = sm.TransitionState(state, parent, block, false) if err != nil { return } @@ -239,7 +260,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st // Commit state objects/accounts to a temporary trie (does not save) // used to calculate the state root. - state.Update() + state.SyncObjects() if header.Root != state.Root() { err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return @@ -248,15 +269,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st // Sync the current block's state to the database state.Sync() - // This puts transactions in a extra db for rpc - for i, tx := range block.Transactions() { - putTx(sm.extraDb, tx, block, uint64(i)) - } - - // store the receipts - putReceipts(sm.extraDb, block.Hash(), receipts) - - return state.Logs(), nil + return state.Logs(), receipts, nil } var ( @@ -327,16 +340,20 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty } // GetBlockReceipts returns the receipts beloniging to the block hash -func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) (receipts types.Receipts, err error) { - return getBlockReceipts(sm.extraDb, bhash) +func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts { + if block := sm.ChainManager().GetBlock(bhash); block != nil { + return GetReceiptsFromBlock(sm.extraDb, block) + } + + return nil } // GetLogs returns the logs of the given block. This method is using a two step approach // where it tries to get it from the (updated) method which gets them from the receipts or // the depricated way by re-processing the block. func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { - receipts, err := sm.GetBlockReceipts(block.Hash()) - if err == nil && len(receipts) > 0 { + receipts := GetReceiptsFromBlock(sm.extraDb, block) + if len(receipts) > 0 { // coalesce logs for _, receipt := range receipts { logs = append(logs, receipt.Logs()...) @@ -362,6 +379,13 @@ func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, check return fmt.Errorf("Block extra data too long (%d)", len(block.Extra)) } + if block.Time > uint64(time.Now().Unix()) { + return BlockFutureErr + } + if block.Time <= parent.Time() { + return BlockEqualTSErr + } + expd := CalcDifficulty(int64(block.Time), int64(parent.Time()), parent.Difficulty()) if expd.Cmp(block.Difficulty) != 0 { return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) @@ -377,20 +401,12 @@ func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, check return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b) } - if int64(block.Time) > time.Now().Unix() { - return BlockFutureErr - } - num := parent.Number() num.Sub(block.Number, num) if num.Cmp(big.NewInt(1)) != 0 { return BlockNumberErr } - if block.Time <= uint64(parent.Time()) { - return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time) - } - if checkPow { // Verify the nonce of the block. Return an error if it's not valid if !pow.Verify(types.NewBlockWithHeader(block)) { @@ -400,55 +416,3 @@ func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, check return nil } - -func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) { - var rdata []byte - rdata, err = db.Get(append(receiptsPre, bhash[:]...)) - - if err == nil { - err = rlp.DecodeBytes(rdata, &receipts) - } else { - glog.V(logger.Detail).Infof("getBlockReceipts error %v\n", err) - } - return -} - -func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint64) { - rlpEnc, err := rlp.EncodeToBytes(tx) - if err != nil { - glog.V(logger.Debug).Infoln("Failed encoding tx", err) - return - } - db.Put(tx.Hash().Bytes(), rlpEnc) - - var txExtra struct { - BlockHash common.Hash - BlockIndex uint64 - Index uint64 - } - txExtra.BlockHash = block.Hash() - txExtra.BlockIndex = block.NumberU64() - txExtra.Index = i - rlpMeta, err := rlp.EncodeToBytes(txExtra) - if err != nil { - glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) - return - } - db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) -} - -func putReceipts(db common.Database, hash common.Hash, receipts types.Receipts) error { - storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) - for i, receipt := range receipts { - storageReceipts[i] = (*types.ReceiptForStorage)(receipt) - } - - bytes, err := rlp.EncodeToBytes(storageReceipts) - if err != nil { - return err - } - - db.Put(append(receiptsPre, hash[:]...), bytes) - - return nil -} diff --git a/core/block_processor_test.go b/core/block_processor_test.go index dc328a3ea..4250b897b 100644 --- a/core/block_processor_test.go +++ b/core/block_processor_test.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -18,7 +34,7 @@ func proc() (*BlockProcessor, *ChainManager) { var mux event.TypeMux genesis := GenesisBlock(0, db) - chainMan, err := NewChainManager(genesis, db, db, thePow(), &mux) + chainMan, err := NewChainManager(genesis, db, db, db, thePow(), &mux) if err != nil { fmt.Println(err) } @@ -64,12 +80,9 @@ func TestPutReceipt(t *testing.T) { Index: 0, }}) - putReceipts(db, hash, types.Receipts{receipt}) - receipts, err := getBlockReceipts(db, hash) - if err != nil { - t.Error("got err:", err) - } - if len(receipts) != 1 { - t.Error("expected to get 1 receipt, got", len(receipts)) + PutReceipts(db, types.Receipts{receipt}) + receipt = GetReceipt(db, common.Hash{}) + if receipt == nil { + t.Error("expected to get 1 receipt, got none.") } } diff --git a/core/blocks.go b/core/blocks.go index f0d39e1e1..b3a559279 100644 --- a/core/blocks.go +++ b/core/blocks.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import "github.com/ethereum/go-ethereum/common" diff --git a/core/canary.go b/core/canary.go index de77c4bba..710e31530 100644 --- a/core/canary.go +++ b/core/canary.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -8,10 +24,10 @@ import ( ) var ( - jeff = common.HexToAddress("9d38997c624a71b21278389ea2fdc460d000e4b2") - vitalik = common.HexToAddress("b1e570be07eaa673e4fd0c8265b64ef739385709") - christoph = common.HexToAddress("529bc43a5d93789fa28de1961db6a07e752204ae") - gav = common.HexToAddress("e3e942b2aa524293c84ff6c7f87a6635790ad5e4") + jeff = common.HexToAddress("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c") + vitalik = common.HexToAddress("1baf27b88c48dd02b744999cf3522766929d2b2a") + christoph = common.HexToAddress("60d11b58744784dc97f878f7e3749c0f1381a004") + gav = common.HexToAddress("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a") ) // Canary will check the 0'd address of the 4 contracts above. diff --git a/core/chain_makers.go b/core/chain_makers.go index 72ae7970e..07670608a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -77,7 +93,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) { if err != nil { panic(err) } - b.statedb.Update() + b.statedb.SyncIntermediate() b.header.GasUsed.Add(b.header.GasUsed, gas) receipt := types.NewReceipt(b.statedb.Root().Bytes(), b.header.GasUsed) logs := b.statedb.GetLogs(tx.Hash()) @@ -135,7 +151,7 @@ func GenerateChain(parent *types.Block, db common.Database, n int, gen func(int, gen(i, b) } AccumulateRewards(statedb, h, b.uncles) - statedb.Update() + statedb.SyncIntermediate() h.Root = statedb.Root() return types.NewBlock(h, b.txs, b.uncles, b.receipts) } @@ -155,7 +171,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header { Root: state.Root(), ParentHash: parent.Hash(), Coinbase: parent.Coinbase(), - Difficulty: CalcDifficulty(time, parent.Time(), parent.Difficulty()), + Difficulty: CalcDifficulty(int64(time), int64(parent.Time()), parent.Difficulty()), GasLimit: CalcGasLimit(parent), GasUsed: new(big.Int), Number: new(big.Int).Add(parent.Number(), common.Big1), @@ -167,7 +183,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header { // InsertChain on the result of makeChain. func newCanonical(n int, db common.Database) (*BlockProcessor, error) { evmux := &event.TypeMux{} - chainman, _ := NewChainManager(GenesisBlock(0, db), db, db, FakePow{}, evmux) + chainman, _ := NewChainManager(GenesisBlock(0, db), db, db, db, FakePow{}, evmux) bman := NewBlockProcessor(db, db, FakePow{}, chainman, evmux) bman.bc.SetProcessor(bman) parent := bman.bc.CurrentBlock() diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index d5125e1c3..2f001be9b 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -58,7 +74,7 @@ func ExampleGenerateChain() { // Import the chain. This runs all block validation rules. evmux := &event.TypeMux{} - chainman, _ := NewChainManager(genesis, db, db, FakePow{}, evmux) + chainman, _ := NewChainManager(genesis, db, db, db, FakePow{}, evmux) chainman.SetProcessor(NewBlockProcessor(db, db, FakePow{}, chainman, evmux)) if i, err := chainman.InsertChain(chain); err != nil { fmt.Printf("insert error (block %d): %v\n", i, err) diff --git a/core/chain_manager.go b/core/chain_manager.go index 808ccd201..bd49bafc2 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -1,7 +1,23 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// Package core implements the Ethereum consensus protocol. package core import ( - "bytes" "fmt" "io" "math/big" @@ -11,19 +27,15 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/compression/rle" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/rlp" "github.com/hashicorp/golang-lru" - "github.com/syndtr/goleveldb/leveldb" ) var ( @@ -40,59 +52,14 @@ const ( blockCacheLimit = 256 maxFutureBlocks = 256 maxTimeFutureBlocks = 30 + checkpointLimit = 200 ) -// CalcDifficulty is the difficulty adjustment algorithm. It returns -// the difficulty that a new block b should have when created at time -// given the parent block's time and difficulty. -func CalcDifficulty(time int64, parentTime int64, parentDiff *big.Int) *big.Int { - diff := new(big.Int) - adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor) - if big.NewInt(time-parentTime).Cmp(params.DurationLimit) < 0 { - diff.Add(parentDiff, adjust) - } else { - diff.Sub(parentDiff, adjust) - } - if diff.Cmp(params.MinimumDifficulty) < 0 { - return params.MinimumDifficulty - } - return diff -} - -// CalcTD computes the total difficulty of block. -func CalcTD(block, parent *types.Block) *big.Int { - if parent == nil { - return block.Difficulty() - } - d := block.Difficulty() - d.Add(d, parent.Td) - return d -} - -// CalcGasLimit computes the gas limit of the next block after parent. -// The result may be modified by the caller. -func CalcGasLimit(parent *types.Block) *big.Int { - decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor) - contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3)) - contrib = contrib.Div(contrib, big.NewInt(2)) - contrib = contrib.Div(contrib, params.GasLimitBoundDivisor) - - gl := new(big.Int).Sub(parent.GasLimit(), decay) - gl = gl.Add(gl, contrib) - gl = gl.Add(gl, big.NewInt(1)) - gl.Set(common.BigMax(gl, params.MinGasLimit)) - - if gl.Cmp(params.GenesisGasLimit) < 0 { - gl.Add(parent.GasLimit(), decay) - gl.Set(common.BigMin(gl, params.GenesisGasLimit)) - } - return gl -} - type ChainManager struct { //eth EthManager blockDb common.Database stateDb common.Database + extraDb common.Database processor types.BlockProcessor eventMux *event.TypeMux genesisBlock *types.Block @@ -101,6 +68,7 @@ type ChainManager struct { chainmu sync.RWMutex tsmu sync.RWMutex + checkpoint int // checkpoint counts towards the new checkpoint td *big.Int currentBlock *types.Block lastBlockHash common.Hash @@ -109,9 +77,8 @@ type ChainManager struct { 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 - pendingBlocks *lru.Cache // pending blocks contain blocks not yet written to the db + cache *lru.Cache // cache is the LRU caching + futureBlocks *lru.Cache // future blocks are blocks added for later processing quit chan struct{} // procInterrupt must be atomically called @@ -121,11 +88,12 @@ type ChainManager struct { pow pow.PoW } -func NewChainManager(genesis *types.Block, blockDb, stateDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) { +func NewChainManager(genesis *types.Block, blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) { cache, _ := lru.New(blockCacheLimit) bc := &ChainManager{ blockDb: blockDb, stateDb: stateDb, + extraDb: extraDb, genesisBlock: GenesisBlock(42, stateDb), eventMux: mux, quit: make(chan struct{}), @@ -240,6 +208,24 @@ 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 { + block := bc.GetBlock(common.BytesToHash(data)) + if block != nil { + err := bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes()) + if err != nil { + glog.Fatalln("db write err:", err) + } + + bc.currentBlock = block + bc.lastBlockHash = block.Hash() + return true + } + } + return false +} + func (bc *ChainManager) setLastState() { data, _ := bc.blockDb.Get([]byte("LastBlock")) if len(data) != 0 { @@ -248,7 +234,12 @@ func (bc *ChainManager) setLastState() { bc.currentBlock = block bc.lastBlockHash = block.Hash() } else { - glog.Fatalf("Fatal. LastBlock not found. Please run removedb and resync") + glog.Infof("LastBlock (%x) not found. Recovering...\n", data) + if bc.recover() { + glog.Infof("Recover successful") + } else { + glog.Fatalf("Recover failed. Please report") + } } } else { bc.Reset() @@ -347,14 +338,19 @@ func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error // insert injects a block into the current chain block chain. Note, this function // assumes that the `mu` mutex is held! func (bc *ChainManager) insert(block *types.Block) { - key := append(blockNumPre, block.Number().Bytes()...) - err := bc.blockDb.Put(key, block.Hash().Bytes()) + err := WriteHead(bc.blockDb, block) if err != nil { glog.Fatal("db write fail:", err) } - err = bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes()) - if err != nil { - glog.Fatal("db write fail:", err) + + bc.checkpoint++ + if bc.checkpoint > checkpointLimit { + err = bc.blockDb.Put([]byte("checkpoint"), block.Hash().Bytes()) + if err != nil { + glog.Fatal("db write fail:", err) + } + + bc.checkpoint = 0 } bc.currentBlock = block @@ -387,12 +383,6 @@ func (bc *ChainManager) HasBlock(hash common.Hash) bool { return true } - if bc.pendingBlocks != nil { - if _, exist := bc.pendingBlocks.Get(hash); exist { - return true - } - } - data, _ := bc.blockDb.Get(append(blockHashPre, hash[:]...)) return len(data) != 0 } @@ -423,26 +413,15 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block { return block.(*types.Block) } - if self.pendingBlocks != nil { - if block, _ := self.pendingBlocks.Get(hash); block != nil { - return block.(*types.Block) - } - } - - data, _ := self.blockDb.Get(append(blockHashPre, hash[:]...)) - if len(data) == 0 { - return nil - } - var block types.StorageBlock - if err := rlp.Decode(bytes.NewReader(data), &block); err != nil { - glog.V(logger.Error).Infof("invalid block RLP for hash %x: %v", hash, err) + block := GetBlockByHash(self.blockDb, hash) + if block == nil { return nil } // Add the block to the cache - self.cache.Add(hash, (*types.Block)(&block)) + self.cache.Add(hash, (*types.Block)(block)) - return (*types.Block)(&block) + return (*types.Block)(block) } func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { @@ -468,12 +447,7 @@ func (self *ChainManager) GetBlocksFromHash(hash common.Hash, n int) (blocks []* // non blocking version func (self *ChainManager) getBlockByNumber(num uint64) *types.Block { - key, _ := self.blockDb.Get(append(blockNumPre, big.NewInt(int64(num)).Bytes()...)) - if len(key) == 0 { - return nil - } - - return self.GetBlock(common.BytesToHash(key)) + return GetBlockByNumber(self.blockDb, num) } func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) { @@ -519,38 +493,13 @@ func (self *ChainManager) procFutureBlocks() { } } -func (self *ChainManager) enqueueForWrite(block *types.Block) { - self.pendingBlocks.Add(block.Hash(), block) -} - -func (self *ChainManager) flushQueuedBlocks() { - db, batchWrite := self.blockDb.(*ethdb.LDBDatabase) - batch := new(leveldb.Batch) - for _, key := range self.pendingBlocks.Keys() { - b, _ := self.pendingBlocks.Get(key) - block := b.(*types.Block) - - enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block)) - key := append(blockHashPre, block.Hash().Bytes()...) - if batchWrite { - batch.Put(key, rle.Compress(enc)) - } else { - self.blockDb.Put(key, enc) - } - } - - if batchWrite { - db.LDB().Write(batch, nil) - } -} - type writeStatus byte const ( - nonStatTy writeStatus = iota - canonStatTy - splitStatTy - sideStatTy + NonStatTy writeStatus = iota + CanonStatTy + SplitStatTy + SideStatTy ) // WriteBlock writes the block to the chain (or pending queue) @@ -567,10 +516,10 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr // during split we merge two different chains and create the new canonical chain err := self.merge(cblock, block) if err != nil { - return nonStatTy, err + return NonStatTy, err } - status = splitStatTy + status = SplitStatTy } self.mu.Lock() @@ -581,20 +530,12 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr self.setTransState(state.New(block.Root(), self.stateDb)) self.txState.SetState(state.New(block.Root(), self.stateDb)) - status = canonStatTy + status = CanonStatTy } else { - status = sideStatTy + status = SideStatTy } - if queued { - // Write block to database. Eventually we'll have to improve on this and throw away blocks that are - // not in the canonical chain. - self.mu.Lock() - self.enqueueForWrite(block) - self.mu.Unlock() - } else { - self.write(block) - } + self.write(block) // Delete from future blocks self.futureBlocks.Remove(block.Hash()) @@ -610,8 +551,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { self.chainmu.Lock() defer self.chainmu.Unlock() - self.pendingBlocks, _ = lru.New(len(chain)) - // A queued approach to delivering events. This is generally // faster than direct delivery and requires much less mutex // acquiring. @@ -629,7 +568,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { // Start the parallel nonce verifier. go verifyNonces(self.pow, chain, nonceQuit, nonceDone) defer close(nonceQuit) - defer self.flushQueuedBlocks() txcount := 0 for i, block := range chain { @@ -662,7 +600,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { // Call in to the block processor and check for errors. It's likely that if one block fails // all others will fail too (unless a known block is returned). - logs, err := self.processor.Process(block) + logs, receipts, err := self.processor.Process(block) if err != nil { if IsKnownBlockErr(err) { stats.ignored++ @@ -673,7 +611,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { // Allow up to MaxFuture second in the future blocks. If this limit // is exceeded the chain is discarded and processed at a later time // if given. - if max := time.Now().Unix() + maxTimeFutureBlocks; block.Time() > max { + if max := time.Now().Unix() + maxTimeFutureBlocks; int64(block.Time()) > max { return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max) } @@ -690,6 +628,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { blockErr(block, err) + go ReportBlock(block, err) + return i, err } @@ -701,19 +641,24 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { return i, err } switch status { - case canonStatTy: + case CanonStatTy: if glog.V(logger.Debug) { glog.Infof("[%v] inserted block #%d (%d TXs %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) } queue[i] = ChainEvent{block, block.Hash(), logs} queueEvent.canonicalCount++ - case sideStatTy: + + // This puts transactions in a extra db for rpc + PutTransactions(self.extraDb, block, block.Transactions()) + // store the receipts + PutReceipts(self.extraDb, receipts) + case SideStatTy: if glog.V(logger.Detail) { glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...). Took %v\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) } queue[i] = ChainSideEvent{block, logs} queueEvent.sideCount++ - case splitStatTy: + case SplitStatTy: queue[i] = ChainSplitEvent{block, logs} queueEvent.splitCount++ } diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index 8b3ea9e85..92f080f01 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -33,7 +49,7 @@ func thePow() pow.PoW { func theChainManager(db common.Database, t *testing.T) *ChainManager { var eventMux event.TypeMux genesis := GenesisBlock(0, db) - chainMan, err := NewChainManager(genesis, db, db, thePow(), &eventMux) + chainMan, err := NewChainManager(genesis, db, db, db, thePow(), &eventMux) if err != nil { t.Error("failed creating chainmanager:", err) t.FailNow() @@ -96,7 +112,7 @@ func printChain(bc *ChainManager) { func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { td := new(big.Int) for _, block := range chainB { - _, err := bman.bc.processor.Process(block) + _, _, err := bman.bc.processor.Process(block) if err != nil { if IsKnownBlockErr(err) { continue @@ -109,8 +125,7 @@ func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { bman.bc.mu.Lock() { - bman.bc.enqueueForWrite(block) - //bman.bc.write(block) + bman.bc.write(block) } bman.bc.mu.Unlock() } @@ -368,7 +383,7 @@ func TestGetBlocksFromHash(t *testing.T) { type bproc struct{} -func (bproc) Process(*types.Block) (state.Logs, error) { return nil, nil } +func (bproc) Process(*types.Block) (state.Logs, types.Receipts, error) { return nil, nil, nil } func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block { var chain []*types.Block @@ -391,7 +406,7 @@ func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block func chm(genesis *types.Block, db common.Database) *ChainManager { var eventMux event.TypeMux - bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}} + bc := &ChainManager{extraDb: db, blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}} bc.cache, _ = lru.New(100) bc.futureBlocks, _ = lru.New(100) bc.processor = bproc{} @@ -480,12 +495,12 @@ func TestGenesisMismatch(t *testing.T) { db, _ := ethdb.NewMemDatabase() var mux event.TypeMux genesis := GenesisBlock(0, db) - _, err := NewChainManager(genesis, db, db, thePow(), &mux) + _, err := NewChainManager(genesis, db, db, db, thePow(), &mux) if err != nil { t.Error(err) } genesis = GenesisBlock(1, db) - _, err = NewChainManager(genesis, db, db, thePow(), &mux) + _, err = NewChainManager(genesis, db, db, db, thePow(), &mux) if err == nil { t.Error("expected genesis mismatch error") } diff --git a/core/chain_util.go b/core/chain_util.go new file mode 100644 index 000000000..96c9a03d8 --- /dev/null +++ b/core/chain_util.go @@ -0,0 +1,114 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +package core + +import ( + "bytes" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" +) + +// CalcDifficulty is the difficulty adjustment algorithm. It returns +// the difficulty that a new block b should have when created at time +// given the parent block's time and difficulty. +func CalcDifficulty(time int64, parentTime int64, parentDiff *big.Int) *big.Int { + diff := new(big.Int) + adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor) + if big.NewInt(time-parentTime).Cmp(params.DurationLimit) < 0 { + diff.Add(parentDiff, adjust) + } else { + diff.Sub(parentDiff, adjust) + } + if diff.Cmp(params.MinimumDifficulty) < 0 { + return params.MinimumDifficulty + } + return diff +} + +// CalcTD computes the total difficulty of block. +func CalcTD(block, parent *types.Block) *big.Int { + if parent == nil { + return block.Difficulty() + } + d := block.Difficulty() + d.Add(d, parent.Td) + return d +} + +// CalcGasLimit computes the gas limit of the next block after parent. +// The result may be modified by the caller. +func CalcGasLimit(parent *types.Block) *big.Int { + decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor) + contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3)) + contrib = contrib.Div(contrib, big.NewInt(2)) + contrib = contrib.Div(contrib, params.GasLimitBoundDivisor) + + gl := new(big.Int).Sub(parent.GasLimit(), decay) + gl = gl.Add(gl, contrib) + gl = gl.Add(gl, big.NewInt(1)) + gl.Set(common.BigMax(gl, params.MinGasLimit)) + + if gl.Cmp(params.GenesisGasLimit) < 0 { + gl.Add(parent.GasLimit(), decay) + gl.Set(common.BigMin(gl, params.GenesisGasLimit)) + } + return gl +} + +// GetBlockByHash returns the block corresponding to the hash or nil if not found +func GetBlockByHash(db common.Database, hash common.Hash) *types.Block { + data, _ := db.Get(append(blockHashPre, hash[:]...)) + if len(data) == 0 { + return nil + } + var block types.StorageBlock + if err := rlp.Decode(bytes.NewReader(data), &block); err != nil { + glog.V(logger.Error).Infof("invalid block RLP for hash %x: %v", hash, err) + return nil + } + return (*types.Block)(&block) +} + +// GetBlockByHash returns the canonical block by number or nil if not found +func GetBlockByNumber(db common.Database, number uint64) *types.Block { + key, _ := db.Get(append(blockNumPre, big.NewInt(int64(number)).Bytes()...)) + if len(key) == 0 { + return nil + } + + return GetBlockByHash(db, common.BytesToHash(key)) +} + +// WriteHead force writes the current head +func WriteHead(db common.Database, block *types.Block) error { + key := append(blockNumPre, block.Number().Bytes()...) + err := db.Put(key, block.Hash().Bytes()) + if err != nil { + return err + } + err = db.Put([]byte("LastBlock"), block.Hash().Bytes()) + if err != nil { + return err + } + return nil +} diff --git a/core/error.go b/core/error.go index 3f3c350df..299317a8e 100644 --- a/core/error.go +++ b/core/error.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -30,7 +46,6 @@ func ParentError(hash common.Hash) error { func IsParentErr(err error) bool { _, ok := err.(*ParentErr) - return ok } @@ -48,7 +63,6 @@ func UncleError(format string, v ...interface{}) error { func IsUncleErr(err error) bool { _, ok := err.(*UncleErr) - return ok } @@ -67,7 +81,6 @@ func ValidationError(format string, v ...interface{}) *ValidationErr { func IsValidationErr(err error) bool { _, ok := err.(*ValidationErr) - return ok } @@ -86,7 +99,6 @@ func NonceError(is, exp uint64) *NonceErr { func IsNonceErr(err error) bool { _, ok := err.(*NonceErr) - return ok } @@ -121,24 +133,6 @@ func InvalidTxError(err error) *InvalidTxErr { func IsInvalidTxErr(err error) bool { _, ok := err.(*InvalidTxErr) - - return ok -} - -type OutOfGasErr struct { - Message string -} - -func OutOfGasError() *OutOfGasErr { - return &OutOfGasErr{Message: "Out of gas"} -} -func (self *OutOfGasErr) Error() string { - return self.Message -} - -func IsOutOfGasErr(err error) bool { - _, ok := err.(*OutOfGasErr) - return ok } diff --git a/core/events.go b/core/events.go index 7b56f8bb6..e47f78923 100644 --- a/core/events.go +++ b/core/events.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( diff --git a/core/execution.go b/core/execution.go index 9fb0210de..a4734dca5 100644 --- a/core/execution.go +++ b/core/execution.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -53,7 +69,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm. if env.Depth() > int(params.CallCreateDepth.Int64()) { caller.ReturnGas(self.Gas, self.price) - return nil, vm.DepthError{} + return nil, vm.DepthError } vsnapshot := env.State().Copy() diff --git a/core/fees.go b/core/fees.go index bbce01b84..0eda52f6d 100644 --- a/core/fees.go +++ b/core/fees.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( diff --git a/core/filter.go b/core/filter.go index fcdf68dd0..277976a55 100644 --- a/core/filter.go +++ b/core/filter.go @@ -1,7 +1,22 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( - "fmt" "math" "github.com/ethereum/go-ethereum/common" @@ -80,7 +95,6 @@ func (self *Filter) Find() state.Logs { done: for i := 0; block != nil; i++ { - fmt.Println(block.NumberU64() == 0) // Quit on latest switch { case block.NumberU64() == 0: diff --git a/core/filter_test.go b/core/filter_test.go index 9a8bc9592..50dc64b2e 100644 --- a/core/filter_test.go +++ b/core/filter_test.go @@ -1 +1,17 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core diff --git a/core/genesis.go b/core/genesis.go index df13466ec..2d369aae0 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -64,7 +80,7 @@ func GenesisBlockForTesting(db common.Database, addr common.Address, balance *bi statedb := state.New(common.Hash{}, db) obj := statedb.GetOrNewStateObject(addr) obj.SetBalance(balance) - statedb.Update() + statedb.SyncObjects() statedb.Sync() block := types.NewBlock(&types.Header{ Difficulty: params.GenesisDifficulty, diff --git a/core/helper_test.go b/core/helper_test.go index a308153aa..fbd900ab7 100644 --- a/core/helper_test.go +++ b/core/helper_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( diff --git a/core/manager.go b/core/manager.go index ba0ecf9d1..a72ef1952 100644 --- a/core/manager.go +++ b/core/manager.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -14,5 +30,6 @@ type Backend interface { TxPool() *TxPool BlockDb() common.Database StateDb() common.Database + ExtraDb() common.Database EventMux() *event.TypeMux } diff --git a/core/state/dump.go b/core/state/dump.go index f6f2f9029..d1273f9b6 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( diff --git a/core/state/errors.go b/core/state/errors.go index 5a847d38b..29acb5cc8 100644 --- a/core/state/errors.go +++ b/core/state/errors.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( diff --git a/core/state/log.go b/core/state/log.go index 882977061..5351c1831 100644 --- a/core/state/log.go +++ b/core/state/log.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( diff --git a/core/state/main_test.go b/core/state/main_test.go index f3d3f7e23..03225ba8c 100644 --- a/core/state/main_test.go +++ b/core/state/main_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( diff --git a/core/state/managed_state.go b/core/state/managed_state.go index aa6650d9b..4dee02992 100644 --- a/core/state/managed_state.go +++ b/core/state/managed_state.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( diff --git a/core/state/managed_state_test.go b/core/state/managed_state_test.go index c7ef2b323..7ae7c0393 100644 --- a/core/state/managed_state_test.go +++ b/core/state/managed_state_test.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( diff --git a/core/state/state_object.go b/core/state/state_object.go index a31c182d2..216ce9132 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( @@ -57,8 +73,6 @@ type StateObject struct { initCode Code // Cached storage (flushed when updated) storage Storage - // Temporary prepaid gas, reward after transition - prepaid *big.Int // Total gas pool is the total amount of gas currently // left if this object is the coinbase. Gas is directly @@ -77,14 +91,10 @@ func (self *StateObject) Reset() { } func NewStateObject(address common.Address, db common.Database) *StateObject { - // This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter. - //address := common.ToAddress(addr) - object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true} object.trie = trie.NewSecure((common.Hash{}).Bytes(), db) object.storage = make(Storage) object.gasPool = new(big.Int) - object.prepaid = new(big.Int) return object } @@ -110,7 +120,6 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data object.trie = trie.NewSecure(extobject.Root[:], db) object.storage = make(map[string]common.Hash) object.gasPool = new(big.Int) - object.prepaid = new(big.Int) object.code, _ = db.Get(extobject.CodeHash) return object @@ -172,7 +181,6 @@ func (self *StateObject) Update() { self.setAddr([]byte(key), value) } - self.storage = make(Storage) } func (c *StateObject) GetInstr(pc *big.Int) *common.Value { diff --git a/core/state/state_test.go b/core/state/state_test.go index 00e133dab..345bd9874 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package state import ( @@ -72,7 +88,7 @@ func TestNull(t *testing.T) { //value := common.FromHex("0x823140710bf13990e4500136726d8b55") var value common.Hash state.SetState(address, common.Hash{}, value) - state.Update() + state.SyncIntermediate() state.Sync() value = state.GetState(address, common.Hash{}) if !common.EmptyHash(value) { diff --git a/core/state/statedb.go b/core/state/statedb.go index f6f63f329..3a2ad10e2 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1,3 +1,20 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// Package state provides a caching layer atop the Ethereum state trie. package state import ( @@ -18,6 +35,7 @@ import ( type StateDB struct { db common.Database trie *trie.SecureTrie + root common.Hash stateObjects map[string]*StateObject @@ -31,7 +49,7 @@ type StateDB struct { // Create a new state from a given trie func New(root common.Hash, db common.Database) *StateDB { trie := trie.NewSecure(root[:], db) - return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} + return &StateDB{root: root, db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} } func (self *StateDB) PrintRoot() { @@ -185,7 +203,7 @@ func (self *StateDB) DeleteStateObject(stateObject *StateObject) { addr := stateObject.Address() self.trie.Delete(addr[:]) - delete(self.stateObjects, addr.Str()) + //delete(self.stateObjects, addr.Str()) } // Retrieve a state object given my the address. Nil if not found @@ -323,7 +341,8 @@ func (self *StateDB) Refunds() *big.Int { return self.refund } -func (self *StateDB) Update() { +// SyncIntermediate updates the intermediate state and all mid steps +func (self *StateDB) SyncIntermediate() { self.refund = new(big.Int) for _, stateObject := range self.stateObjects { @@ -340,6 +359,24 @@ func (self *StateDB) Update() { } } +// SyncObjects syncs the changed objects to the trie +func (self *StateDB) SyncObjects() { + self.trie = trie.NewSecure(self.root[:], self.db) + + self.refund = new(big.Int) + + for _, stateObject := range self.stateObjects { + if stateObject.remove { + self.DeleteStateObject(stateObject) + } else { + stateObject.Update() + + self.UpdateStateObject(stateObject) + } + stateObject.dirty = false + } +} + // Debug stuff func (self *StateDB) CreateOutputForDiff() { for _, stateObject := range self.stateObjects { diff --git a/core/state_transition.go b/core/state_transition.go index e2212dfef..aacf53799 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -7,7 +23,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/params" @@ -56,11 +71,6 @@ type Message interface { Data() []byte } -func AddressFromMessage(msg Message) common.Address { - from, _ := msg.From() - return crypto.CreateAddress(from, msg.Nonce()) -} - func MessageCreatesContract(msg Message) bool { return msg.To() == nil } @@ -128,7 +138,7 @@ func (self *StateTransition) To() *state.StateObject { func (self *StateTransition) UseGas(amount *big.Int) error { if self.gas.Cmp(amount) < 0 { - return OutOfGasError() + return vm.OutOfGasError } self.gas.Sub(self.gas, amount) @@ -209,16 +219,23 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er glog.V(logger.Core).Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas) } } + glog.V(logger.Core).Infoln("VM create err:", err) } else { // Increment the nonce for the next transaction self.state.SetNonce(sender.Address(), sender.Nonce()+1) ret, err = vmenv.Call(sender, self.To().Address(), self.data, self.gas, self.gasPrice, self.value) + glog.V(logger.Core).Infoln("VM call err:", err) } if err != nil && IsValueTransferErr(err) { return nil, nil, InvalidTxError(err) } + // We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up + if err != nil { + err = nil + } + if vm.Debug { vm.StdErrFormat(vmenv.StructLogs()) } diff --git a/core/transaction_pool.go b/core/transaction_pool.go index bf28647c3..e02a3a6ac 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -29,7 +45,7 @@ var ( ) const ( - maxQueued = 200 // max limit of queued txs per address + maxQueued = 64 // max limit of queued txs per address ) type stateFn func() *state.StateDB @@ -65,7 +81,7 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func( gasLimit: gasLimitFn, minGasPrice: new(big.Int), pendingState: state.ManageState(currentStateFn()), - events: eventMux.Subscribe(ChainEvent{}, GasPriceChanged{}), + events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}), } go pool.eventLoop() @@ -80,7 +96,7 @@ func (pool *TxPool) eventLoop() { pool.mu.Lock() switch ev := ev.(type) { - case ChainEvent: + case ChainHeadEvent: pool.resetState() case GasPriceChanged: pool.minGasPrice = ev.Price @@ -129,6 +145,17 @@ func (pool *TxPool) State() *state.ManagedState { return pool.pendingState } +func (pool *TxPool) Stats() (pending int, queued int) { + pool.mu.RLock() + defer pool.mu.RUnlock() + + pending = len(pool.pending) + for _, txs := range pool.queue { + queued += len(txs) + } + return +} + // validateTx checks whether a transaction is valid according // to the consensus rules. func (pool *TxPool) validateTx(tx *types.Transaction) error { @@ -214,9 +241,6 @@ func (self *TxPool) add(tx *types.Transaction) error { glog.Infof("(t) %x => %s (%v) %x\n", from, toname, tx.Value, hash) } - // check and validate the queueue - self.checkQueue() - return nil } @@ -245,11 +269,17 @@ func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Trans } // Add queues a single transaction in the pool if it is valid. -func (self *TxPool) Add(tx *types.Transaction) error { +func (self *TxPool) Add(tx *types.Transaction) (err error) { self.mu.Lock() defer self.mu.Unlock() - return self.add(tx) + err = self.add(tx) + if err == nil { + // check and validate the queueue + self.checkQueue() + } + + return } // AddTransactions attempts to queue all valid transactions in txs. @@ -265,6 +295,9 @@ func (self *TxPool) AddTransactions(txs []*types.Transaction) { glog.V(logger.Debug).Infof("tx %x\n", h[:4]) } } + + // check and validate the queueue + self.checkQueue() } // GetTransaction returns a transaction if it is contained in the pool @@ -327,6 +360,23 @@ func (self *TxPool) RemoveTransactions(txs types.Transactions) { } } +func (pool *TxPool) removeTx(hash common.Hash) { + // delete from pending pool + delete(pool.pending, hash) + // delete from queue + for address, txs := range pool.queue { + if _, ok := txs[hash]; ok { + if len(txs) == 1 { + // if only one tx, remove entire address entry. + delete(pool.queue, address) + } else { + delete(txs, hash) + } + break + } + } +} + // checkQueue moves transactions that have become processable to main pool. func (pool *TxPool) checkQueue() { state := pool.pendingState @@ -354,13 +404,19 @@ func (pool *TxPool) checkQueue() { for i, e := range addq { // start deleting the transactions from the queue if they exceed the limit if i > maxQueued { - if glog.V(logger.Debug) { - glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:])) - } delete(pool.queue[address], e.hash) continue } + if e.Nonce() > guessedNonce { + if len(addq)-i > maxQueued { + if glog.V(logger.Debug) { + glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:])) + } + for j := i + maxQueued; j < len(addq); j++ { + delete(txs, addq[j].hash) + } + } break } delete(txs, e.hash) @@ -373,23 +429,6 @@ func (pool *TxPool) checkQueue() { } } -func (pool *TxPool) removeTx(hash common.Hash) { - // delete from pending pool - delete(pool.pending, hash) - // delete from queue - for address, txs := range pool.queue { - if _, ok := txs[hash]; ok { - if len(txs) == 1 { - // if only one tx, remove entire address entry. - delete(pool.queue, address) - } else { - delete(txs, hash) - } - break - } - } -} - // validatePool removes invalid and processed transactions from the main pool. func (pool *TxPool) validatePool() { state := pool.currentState() diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go index ff8b9c730..fdd0a7872 100644 --- a/core/transaction_pool_test.go +++ b/core/transaction_pool_test.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -181,6 +197,8 @@ func TestTransactionDoubleNonce(t *testing.T) { if err := pool.add(tx2); err != nil { t.Error("didn't expect error", err) } + + pool.checkQueue() if len(pool.pending) != 2 { t.Error("expected 2 pending txs. Got", len(pool.pending)) } diff --git a/core/transaction_util.go b/core/transaction_util.go new file mode 100644 index 000000000..0efeddfde --- /dev/null +++ b/core/transaction_util.go @@ -0,0 +1,101 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +package core + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" + "github.com/ethereum/go-ethereum/rlp" +) + +var receiptsPre = []byte("receipts-") + +// PutTransactions stores the transactions in the given database +func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { + 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) + + var txExtra struct { + BlockHash common.Hash + BlockIndex uint64 + Index uint64 + } + txExtra.BlockHash = block.Hash() + txExtra.BlockIndex = block.NumberU64() + txExtra.Index = uint64(i) + rlpMeta, err := rlp.EncodeToBytes(txExtra) + if err != nil { + glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) + return + } + db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + } +} + +// PutReceipts stores the receipts in the current database +func PutReceipts(db common.Database, receipts types.Receipts) error { + 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 { + return err + } + } + + return nil +} + +// GetReceipt returns a receipt by hash +func GetReceipt(db common.Database, txHash common.Hash) *types.Receipt { + data, _ := db.Get(append(receiptsPre, txHash[:]...)) + if len(data) == 0 { + return nil + } + + var receipt types.Receipt + err := rlp.DecodeBytes(data, &receipt) + if err != nil { + glog.V(logger.Core).Infoln("GetReceipt err:", err) + } + return &receipt +} + +// GetReceiptFromBlock returns all receipts with the given block +func GetReceiptsFromBlock(db common.Database, block *types.Block) types.Receipts { + // at some point we want: + //receipts := make(types.Receipts, len(block.Transactions())) + // but since we need to support legacy, we can't (yet) + var receipts types.Receipts + for _, tx := range block.Transactions() { + if receipt := GetReceipt(db, tx.Hash()); receipt != nil { + receipts = append(receipts, receipt) + } + } + + return receipts +} diff --git a/core/types/block.go b/core/types/block.go index b7eb700ca..562fa64b9 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -1,3 +1,20 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// Package types contains data types related to Ethereum consensus. package types import ( @@ -290,7 +307,7 @@ func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) } func (b *Block) Bloom() Bloom { return b.header.Bloom } func (b *Block) Coinbase() common.Address { return b.header.Coinbase } -func (b *Block) Time() int64 { return int64(b.header.Time) } +func (b *Block) Time() uint64 { return b.header.Time } func (b *Block) Root() common.Hash { return b.header.Root } func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } func (b *Block) TxHash() common.Hash { return b.header.TxHash } diff --git a/core/types/block_test.go b/core/types/block_test.go index 03e6881be..2c1b18b5d 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( @@ -31,7 +47,7 @@ func TestBlockEncoding(t *testing.T) { check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e")) check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4)) - check("Time", block.Time(), int64(1426516743)) + check("Time", block.Time(), uint64(1426516743)) check("Size", block.Size(), common.StorageSize(len(blockEnc))) tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil) diff --git a/core/types/bloom9.go b/core/types/bloom9.go index aa76a2e9d..565c831ee 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( diff --git a/core/types/bloom9_test.go b/core/types/bloom9_test.go index 3c95772ec..a3cc1922a 100644 --- a/core/types/bloom9_test.go +++ b/core/types/bloom9_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types /* diff --git a/core/types/common.go b/core/types/common.go index dbdaaba0c..4a8a7b5c4 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( @@ -10,7 +26,7 @@ import ( ) type BlockProcessor interface { - Process(*Block) (state.Logs, error) + Process(*Block) (state.Logs, Receipts, error) } const bloomLength = 256 diff --git a/core/types/derive_sha.go b/core/types/derive_sha.go index f25e5937e..c446a5f27 100644 --- a/core/types/derive_sha.go +++ b/core/types/derive_sha.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( diff --git a/core/types/receipt.go b/core/types/receipt.go index 6b4024ada..7c44e6307 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( @@ -15,7 +31,10 @@ type Receipt struct { PostState []byte CumulativeGasUsed *big.Int Bloom Bloom + TxHash common.Hash + ContractAddress common.Address logs state.Logs + GasUsed *big.Int } func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt { @@ -39,12 +58,15 @@ func (self *Receipt) DecodeRLP(s *rlp.Stream) error { PostState []byte CumulativeGasUsed *big.Int Bloom Bloom + TxHash common.Hash + ContractAddress common.Address Logs state.Logs + GasUsed *big.Int } if err := s.Decode(&r); err != nil { return err } - self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs = r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs + self.PostState, self.CumulativeGasUsed, self.Bloom, self.TxHash, self.ContractAddress, self.logs, self.GasUsed = r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, r.Logs, r.GasUsed return nil } @@ -56,7 +78,7 @@ func (self *ReceiptForStorage) EncodeRLP(w io.Writer) error { for i, log := range self.logs { storageLogs[i] = (*state.LogForStorage)(log) } - return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, storageLogs}) + return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.TxHash, self.ContractAddress, storageLogs, self.GasUsed}) } func (self *Receipt) RlpEncode() []byte { diff --git a/core/types/transaction.go b/core/types/transaction.go index 95deac36e..09fde8ebe 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( @@ -15,6 +31,8 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) +var ErrInvalidSig = errors.New("invalid v, r, s values") + func IsContractAddr(addr []byte) bool { return len(addr) == 0 } @@ -116,11 +134,21 @@ func (tx *Transaction) To() *common.Address { } } +// Hash hashes the RLP encoding of tx. +// It uniquely identifies the transaction. func (tx *Transaction) Hash() common.Hash { if hash := tx.hash.Load(); hash != nil { return hash.(common.Hash) } - v := rlpHash([]interface{}{ + v := rlpHash(tx) + tx.hash.Store(v) + return v +} + +// SigHash returns the hash to be signed by the sender. +// It does not uniquely identify the transaction. +func (tx *Transaction) SigHash() common.Hash { + return rlpHash([]interface{}{ tx.data.AccountNonce, tx.data.Price, tx.data.GasLimit, @@ -128,8 +156,6 @@ func (tx *Transaction) Hash() common.Hash { tx.data.Amount, tx.data.Payload, }) - tx.hash.Store(v) - return v } func (tx *Transaction) Size() common.StorageSize { @@ -169,7 +195,7 @@ func (tx *Transaction) SignatureValues() (v byte, r *big.Int, s *big.Int) { func (tx *Transaction) publicKey() ([]byte, error) { if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S) { - return nil, errors.New("invalid v, r, s values") + return nil, ErrInvalidSig } // encode the signature in uncompressed format @@ -180,7 +206,7 @@ func (tx *Transaction) publicKey() ([]byte, error) { sig[64] = tx.data.V - 27 // recover the public key from the signature - hash := tx.Hash() + hash := tx.SigHash() pub, err := crypto.Ecrecover(hash[:], sig) if err != nil { glog.V(logger.Error).Infof("Could not get pubkey from signature: ", err) @@ -204,7 +230,7 @@ func (tx *Transaction) WithSignature(sig []byte) (*Transaction, error) { } func (tx *Transaction) SignECDSA(prv *ecdsa.PrivateKey) (*Transaction, error) { - h := tx.Hash() + h := tx.SigHash() sig, err := crypto.Sign(h[:], prv) if err != nil { return nil, err diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index dd9c5e87b..77717ce28 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package types import ( @@ -34,11 +50,11 @@ var ( ) ) -func TestTransactionHash(t *testing.T) { - if emptyTx.Hash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") { +func TestTransactionSigHash(t *testing.T) { + if emptyTx.SigHash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") { t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash()) } - if rightvrsTx.Hash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") { + if rightvrsTx.SigHash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") { t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash()) } } diff --git a/core/vm/analysis.go b/core/vm/analysis.go index a7aa8da39..ba0a02e0a 100644 --- a/core/vm/analysis.go +++ b/core/vm/analysis.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/asm.go b/core/vm/asm.go index 83fcb0e08..c5c6ef269 100644 --- a/core/vm/asm.go +++ b/core/vm/asm.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/common.go b/core/vm/common.go index 7b8b7dc4d..c40712bfe 100644 --- a/core/vm/common.go +++ b/core/vm/common.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/context.go b/core/vm/context.go index e33324b53..05bcee86c 100644 --- a/core/vm/context.go +++ b/core/vm/context.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 90e356b1d..f32df3d41 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/disasm.go b/core/vm/disasm.go index 858ee684a..bb07b5816 100644 --- a/core/vm/disasm.go +++ b/core/vm/disasm.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import "fmt" diff --git a/core/vm/environment.go b/core/vm/environment.go index c103049a2..2368b5170 100644 --- a/core/vm/environment.go +++ b/core/vm/environment.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( @@ -17,7 +33,7 @@ type Environment interface { BlockNumber() *big.Int GetHash(n uint64) common.Hash Coinbase() common.Address - Time() int64 + Time() uint64 Difficulty() *big.Int GasLimit() *big.Int Transfer(from, to Account, amount *big.Int) error diff --git a/core/vm/errors.go b/core/vm/errors.go index 799eb6797..d0c332068 100644 --- a/core/vm/errors.go +++ b/core/vm/errors.go @@ -1,21 +1,30 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/params" ) -type OutOfGasError struct{} - -func (self OutOfGasError) Error() string { - return "Out Of Gas" -} - -func IsOOGErr(err error) bool { - _, ok := err.(OutOfGasError) - return ok -} +var OutOfGasError = errors.New("Out of gas") +var DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth) type StackError struct { req, has int @@ -29,18 +38,7 @@ func (self StackError) Error() string { return fmt.Sprintf("stack error! require %v, have %v", self.req, self.has) } -func IsStack(err error) bool { +func IsStackErr(err error) bool { _, ok := err.(StackError) return ok } - -type DepthError struct{} - -func (self DepthError) Error() string { - return fmt.Sprintf("Max call depth exceeded (%d)", params.CallCreateDepth) -} - -func IsDepthErr(err error) bool { - _, ok := err.(DepthError) - return ok -} diff --git a/core/vm/gas.go b/core/vm/gas.go index 32f5fec04..1710ef0c9 100644 --- a/core/vm/gas.go +++ b/core/vm/gas.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/logger.go b/core/vm/logger.go index 0e2a417ae..a99b268b4 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/memory.go b/core/vm/memory.go index ea2ee80fb..413507ae5 100644 --- a/core/vm/memory.go +++ b/core/vm/memory.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import "fmt" diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 1ea80a212..5c74220a5 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/stack.go b/core/vm/stack.go index 2be5c3dbe..31541f38f 100644 --- a/core/vm/stack.go +++ b/core/vm/stack.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm import ( diff --git a/core/vm/virtual_machine.go b/core/vm/virtual_machine.go index 1fd1dcd88..44d3d5d7e 100644 --- a/core/vm/virtual_machine.go +++ b/core/vm/virtual_machine.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package vm type VirtualMachine interface { diff --git a/core/vm/vm.go b/core/vm/vm.go index 9e092300d..9b3fd0009 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -1,3 +1,20 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// Package vm implements the Ethereum Virtual Machine. package vm import ( @@ -116,7 +133,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) { context.UseGas(context.Gas) - return context.Return(nil), OutOfGasError{} + return context.Return(nil), OutOfGasError } // Resize the memory calculated previously mem.Resize(newMemSize.Uint64()) @@ -444,7 +461,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) { case TIMESTAMP: time := self.env.Time() - stack.push(big.NewInt(time)) + stack.push(new(big.Int).SetUint64(time)) case NUMBER: number := self.env.BlockNumber() @@ -789,7 +806,7 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, context *Con return context.Return(ret), nil } else { - return nil, OutOfGasError{} + return nil, OutOfGasError } } diff --git a/core/vm/vm_jit.go b/core/vm/vm_jit.go index 991ade318..34f45b5f4 100644 --- a/core/vm/vm_jit.go +++ b/core/vm/vm_jit.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + // +build evmjit package vm @@ -18,10 +34,12 @@ import ( "bytes" "errors" "fmt" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/crypto" "math/big" "unsafe" + + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) type JitVm struct { diff --git a/core/vm/vm_jit_fake.go b/core/vm/vm_jit_fake.go index d6b5be45b..66a6d833d 100644 --- a/core/vm/vm_jit_fake.go +++ b/core/vm/vm_jit_fake.go @@ -1,3 +1,19 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + // +build !evmjit package vm diff --git a/core/vm_env.go b/core/vm_env.go index 6dd83acde..8a39af196 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -1,3 +1,19 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + package core import ( @@ -33,7 +49,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, header *type func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f } func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number } func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase } -func (self *VMEnv) Time() int64 { return int64(self.header.Time) } +func (self *VMEnv) Time() uint64 { return self.header.Time } func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty } func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit } func (self *VMEnv) Value() *big.Int { return self.msg.Value() } |