diff options
author | Taylor Gerring <taylor.gerring@gmail.com> | 2015-01-21 03:22:38 +0800 |
---|---|---|
committer | Taylor Gerring <taylor.gerring@gmail.com> | 2015-01-21 03:22:38 +0800 |
commit | d92fde698031758f64fcabe7af354360a93f6326 (patch) | |
tree | 5f843fe17762e0aa87a0e790d527886f2cc8eea5 /core | |
parent | 499bc404e818848e53c8c7f4f6d1bfe2349e97ae (diff) | |
parent | 87f50659db7a4bf194769b05f541d2ccf02f4fc8 (diff) | |
download | dexon-d92fde698031758f64fcabe7af354360a93f6326.tar dexon-d92fde698031758f64fcabe7af354360a93f6326.tar.gz dexon-d92fde698031758f64fcabe7af354360a93f6326.tar.bz2 dexon-d92fde698031758f64fcabe7af354360a93f6326.tar.lz dexon-d92fde698031758f64fcabe7af354360a93f6326.tar.xz dexon-d92fde698031758f64fcabe7af354360a93f6326.tar.zst dexon-d92fde698031758f64fcabe7af354360a93f6326.zip |
Merge branch 'develop' into jsonrpc
Diffstat (limited to 'core')
-rw-r--r-- | core/block_processor.go | 104 | ||||
-rw-r--r-- | core/chain_manager.go | 84 | ||||
-rw-r--r-- | core/chain_manager_test.go | 46 | ||||
-rw-r--r-- | core/execution.go | 28 | ||||
-rw-r--r-- | core/genesis.go | 6 | ||||
-rw-r--r-- | core/helper_test.go | 1 | ||||
-rw-r--r-- | core/state_transition.go | 3 | ||||
-rw-r--r-- | core/transaction_pool.go | 10 | ||||
-rw-r--r-- | core/transaction_pool_test.go | 20 | ||||
-rw-r--r-- | core/types/block.go | 22 | ||||
-rw-r--r-- | core/types/derive_sha.go | 6 |
11 files changed, 187 insertions, 143 deletions
diff --git a/core/block_processor.go b/core/block_processor.go index 83399f472..aa8fcc9e7 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "errors" "fmt" "math/big" "sync" @@ -36,6 +35,7 @@ type EthManager interface { } type BlockProcessor struct { + db ethutil.Database // Mutex for locking the block processor. Blocks can only be handled one at a time mutex sync.Mutex // Canonical block chain @@ -57,8 +57,9 @@ type BlockProcessor struct { eventMux *event.TypeMux } -func NewBlockProcessor(txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { +func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { sm := &BlockProcessor{ + db: db, mem: make(map[string]*big.Int), Pow: ezp.New(), bc: chainManager, @@ -170,7 +171,8 @@ func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, msgs state.M func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) { sm.lastAttemptedBlock = block - state := state.New(parent.Trie().Copy()) + state := state.New(parent.Root(), sm.db) + //state := state.New(parent.Trie().Copy()) // Block validation if err = sm.ValidateBlock(block, parent); err != nil { @@ -214,52 +216,33 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big return } - // Calculate the new total difficulty and sync back to the db - if td, ok := sm.CalculateTD(block); ok { - // Sync the current block's state to the database and cancelling out the deferred Undo - state.Sync() - - state.Manifest().SetHash(block.Hash()) - - messages := state.Manifest().Messages - state.Manifest().Reset() - - chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash()[0:4]) - - sm.txpool.RemoveSet(block.Transactions()) - - return td, messages, nil - } else { - return nil, nil, errors.New("total diff failed") - } -} - -func (sm *BlockProcessor) CalculateTD(block *types.Block) (*big.Int, bool) { - uncleDiff := new(big.Int) - for _, uncle := range block.Uncles() { - uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) - } - - // TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty - td := new(big.Int) - td = td.Add(sm.bc.Td(), uncleDiff) - td = td.Add(td, block.Header().Difficulty) - - // The new TD will only be accepted if the new difficulty is - // is greater than the previous. - if td.Cmp(sm.bc.Td()) > 0 { - return td, true - } - - return nil, false + // Calculate the td for this block + td = CalculateTD(block, parent) + // Sync the current block's state to the database and cancelling out the deferred Undo + state.Sync() + // Set the block hashes for the current messages + state.Manifest().SetHash(block.Hash()) + messages = state.Manifest().Messages + // Reset the manifest XXX We need this? + state.Manifest().Reset() + // Remove transactions from the pool + sm.txpool.RemoveSet(block.Transactions()) + + chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash()[0:4]) + + return td, messages, nil } // Validates the current block. Returns an error if the block was invalid, // an uncle or anything that isn't on the current block chain. // Validation validates easy over difficult (dagger takes longer time = difficult) func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { + if len(block.Header().Extra) > 1024 { + return fmt.Errorf("Block extra data too long (%d)", len(block.Header().Extra)) + } + expd := CalcDifficulty(block, parent) - if expd.Cmp(block.Header().Difficulty) < 0 { + if expd.Cmp(block.Header().Difficulty) != 0 { return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) } @@ -286,32 +269,38 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error { reward := new(big.Int).Set(BlockReward) - knownUncles := set.New() - for _, uncle := range parent.Uncles() { - knownUncles.Add(string(uncle.Hash())) + ancestors := set.New() + for _, ancestor := range sm.bc.GetAncestors(block, 7) { + ancestors.Add(string(ancestor.Hash())) } - nonces := ethutil.NewSet(block.Header().Nonce) + uncles := set.New() + uncles.Add(string(block.Hash())) for _, uncle := range block.Uncles() { - if nonces.Include(uncle.Nonce) { + if uncles.Has(string(uncle.Hash())) { // Error not unique return UncleError("Uncle not unique") } + uncles.Add(string(uncle.Hash())) - uncleParent := sm.bc.GetBlock(uncle.ParentHash) - if uncleParent == nil { + if !ancestors.Has(string(uncle.ParentHash)) { return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } - if uncleParent.Header().Number.Cmp(new(big.Int).Sub(parent.Header().Number, big.NewInt(6))) < 0 { - return UncleError("Uncle too old") - } + /* + uncleParent := sm.bc.GetBlock(uncle.ParentHash) + if uncleParent == nil { + return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) + } - if knownUncles.Has(string(uncle.Hash())) { - return UncleError("Uncle in chain") - } + if uncleParent.Number().Cmp(new(big.Int).Sub(parent.Number(), big.NewInt(6))) < 0 { + return UncleError("Uncle too old") + } - nonces.Insert(uncle.Nonce) + if knownUncles.Has(string(uncle.Hash())) { + return UncleError("Uncle in chain") + } + */ r := new(big.Int) r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16)) @@ -347,7 +336,8 @@ func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Mes var ( parent = sm.bc.GetBlock(block.Header().ParentHash) - state = state.New(parent.Trie().Copy()) + //state = state.New(parent.Trie().Copy()) + state = state.New(parent.Root(), sm.db) ) defer state.Reset() diff --git a/core/chain_manager.go b/core/chain_manager.go index 82b17cd93..c68b7cfc2 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -23,17 +23,30 @@ type StateQuery interface { func CalcDifficulty(block, parent *types.Block) *big.Int { diff := new(big.Int) - bh, ph := block.Header(), parent.Header() - adjust := new(big.Int).Rsh(ph.Difficulty, 10) - if bh.Time >= ph.Time+5 { - diff.Sub(ph.Difficulty, adjust) + adjust := new(big.Int).Rsh(parent.Difficulty(), 10) + if block.Time() >= parent.Time()+8 { + diff.Sub(parent.Difficulty(), adjust) } else { - diff.Add(ph.Difficulty, adjust) + diff.Add(parent.Difficulty(), adjust) } return diff } +func CalculateTD(block, parent *types.Block) *big.Int { + uncleDiff := new(big.Int) + for _, uncle := range block.Uncles() { + uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) + } + + // TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty + td := new(big.Int) + td = td.Add(parent.Td, uncleDiff) + td = td.Add(td, block.Header().Difficulty) + + return td +} + func CalcGasLimit(parent, block *types.Block) *big.Int { if block.Number().Cmp(big.NewInt(0)) == 0 { return ethutil.BigPow(10, 6) @@ -55,6 +68,7 @@ func CalcGasLimit(parent, block *types.Block) *big.Int { type ChainManager struct { //eth EthManager + db ethutil.Database processor types.BlockProcessor eventMux *event.TypeMux genesisBlock *types.Block @@ -96,13 +110,9 @@ func (self *ChainManager) CurrentBlock() *types.Block { return self.currentBlock } -func NewChainManager(mux *event.TypeMux) *ChainManager { - bc := &ChainManager{} - bc.genesisBlock = GenesisBlock() - bc.eventMux = mux - +func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager { + bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux} bc.setLastBlock() - bc.transState = bc.State().Copy() return bc @@ -120,7 +130,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) { } func (self *ChainManager) State() *state.StateDB { - return state.New(self.CurrentBlock().Trie()) + return state.New(self.CurrentBlock().Root(), self.db) } func (self *ChainManager) TransState() *state.StateDB { @@ -128,7 +138,7 @@ func (self *ChainManager) TransState() *state.StateDB { } func (bc *ChainManager) setLastBlock() { - data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) + data, _ := bc.db.Get([]byte("LastBlock")) if len(data) != 0 { var block types.Block rlp.Decode(bytes.NewReader(data), &block) @@ -137,12 +147,12 @@ func (bc *ChainManager) setLastBlock() { bc.lastBlockNumber = block.Header().Number.Uint64() // Set the last know difficulty (might be 0x0 as initial value, Genesis) - bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) + bc.td = ethutil.BigD(bc.db.LastKnownTD()) } else { bc.Reset() } - chainlogger.Infof("Last block (#%d) %x\n", bc.lastBlockNumber, bc.currentBlock.Hash()) + chainlogger.Infof("Last block (#%d) %x TD=%v\n", bc.lastBlockNumber, bc.currentBlock.Hash(), bc.td) } // Block creation & chain handling @@ -183,7 +193,7 @@ func (bc *ChainManager) Reset() { defer bc.mu.Unlock() for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.Header().ParentHash) { - ethutil.Config.Db.Delete(block.Hash()) + bc.db.Delete(block.Hash()) } // Prepare the genesis block @@ -210,7 +220,7 @@ func (self *ChainManager) Export() []byte { func (bc *ChainManager) insert(block *types.Block) { encodedBlock := ethutil.Encode(block) - ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock) + bc.db.Put([]byte("LastBlock"), encodedBlock) bc.currentBlock = block bc.lastBlockHash = block.Hash() } @@ -218,8 +228,8 @@ func (bc *ChainManager) insert(block *types.Block) { func (bc *ChainManager) write(block *types.Block) { bc.writeBlockInfo(block) - encodedBlock := ethutil.Encode(block) - ethutil.Config.Db.Put(block.Hash(), encodedBlock) + encodedBlock := ethutil.Encode(block.RlpDataForStorage()) + bc.db.Put(block.Hash(), encodedBlock) } // Accessors @@ -229,7 +239,7 @@ func (bc *ChainManager) Genesis() *types.Block { // Block fetching methods func (bc *ChainManager) HasBlock(hash []byte) bool { - data, _ := ethutil.Config.Db.Get(hash) + data, _ := bc.db.Get(hash) return len(data) != 0 } @@ -241,20 +251,18 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain // XXX Could be optimised by using a different database which only holds hashes (i.e., linked list) for i := uint64(0); i < max; i++ { + block = self.GetBlock(block.Header().ParentHash) chain = append(chain, block.Hash()) - if block.Header().Number.Cmp(ethutil.Big0) <= 0 { break } - - block = self.GetBlock(block.Header().ParentHash) } return } func (self *ChainManager) GetBlock(hash []byte) *types.Block { - data, _ := ethutil.Config.Db.Get(hash) + data, _ := self.db.Get(hash) if len(data) == 0 { return nil } @@ -267,6 +275,28 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block { return &block } +func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) { + for i := 0; block != nil && i < length; i++ { + uncles = append(uncles, block.Uncles()...) + block = self.GetBlock(block.ParentHash()) + } + + return +} + +func (self *ChainManager) GetAncestors(block *types.Block, length int) (blocks []*types.Block) { + for i := 0; i < length; i++ { + block = self.GetBlock(block.ParentHash()) + if block == nil { + break + } + + blocks = append(blocks, block) + } + + return +} + func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { self.mu.RLock() defer self.mu.RUnlock() @@ -286,7 +316,7 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { } func (bc *ChainManager) setTotalDifficulty(td *big.Int) { - ethutil.Config.Db.Put([]byte("LTD"), td.Bytes()) + bc.db.Put([]byte("LTD"), td.Bytes()) bc.td = td } @@ -343,12 +373,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { cblock := self.currentBlock if td.Cmp(self.td) > 0 { if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 { - chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Header().Number, block.Hash()[:4], cblock.Header().Number, cblock.Hash()[:4]) + chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td) } self.setTotalDifficulty(td) self.insert(block) - self.transState = state.New(cblock.Trie().Copy()) + self.transState = state.New(cblock.Root(), self.db) //state.New(cblock.Trie().Copy()) } } diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index 2ed3c6c9e..f382516b7 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -1,10 +1,10 @@ package core import ( + "bytes" "fmt" "os" "path" - "reflect" "runtime" "strconv" "testing" @@ -21,14 +21,6 @@ func init() { ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") } -func reset() { - db, err := ethdb.NewMemDatabase() - if err != nil { - panic("Could not create mem-db, failing") - } - ethutil.Config.Db = db -} - func loadChain(fn string, t *testing.T) (types.Blocks, error) { fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) if err != nil { @@ -54,7 +46,7 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t * } func TestChainInsertions(t *testing.T) { - reset() + db, _ := ethdb.NewMemDatabase() chain1, err := loadChain("valid1", t) if err != nil { @@ -69,9 +61,9 @@ func TestChainInsertions(t *testing.T) { } var eventMux event.TypeMux - chainMan := NewChainManager(&eventMux) + chainMan := NewChainManager(db, &eventMux) txPool := NewTxPool(&eventMux) - blockMan := NewBlockManager(txPool, chainMan, &eventMux) + blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux) chainMan.SetProcessor(blockMan) const max = 2 @@ -84,17 +76,17 @@ func TestChainInsertions(t *testing.T) { <-done } - if reflect.DeepEqual(chain2[len(chain2)-1], chainMan.CurrentBlock()) { + if bytes.Equal(chain2[len(chain2)-1].Hash(), chainMan.CurrentBlock().Hash()) { t.Error("chain2 is canonical and shouldn't be") } - if !reflect.DeepEqual(chain1[len(chain1)-1], chainMan.CurrentBlock()) { + if !bytes.Equal(chain1[len(chain1)-1].Hash(), chainMan.CurrentBlock().Hash()) { t.Error("chain1 isn't canonical and should be") } } func TestChainMultipleInsertions(t *testing.T) { - reset() + db, _ := ethdb.NewMemDatabase() const max = 4 chains := make([]types.Blocks, max) @@ -113,9 +105,9 @@ func TestChainMultipleInsertions(t *testing.T) { } } var eventMux event.TypeMux - chainMan := NewChainManager(&eventMux) + chainMan := NewChainManager(db, &eventMux) txPool := NewTxPool(&eventMux) - blockMan := NewBlockManager(txPool, chainMan, &eventMux) + blockMan := NewBlockProcessor(db, txPool, chainMan, &eventMux) chainMan.SetProcessor(blockMan) done := make(chan bool, max) for i, chain := range chains { @@ -132,7 +124,25 @@ func TestChainMultipleInsertions(t *testing.T) { <-done } - if !reflect.DeepEqual(chains[longest][len(chains[longest])-1], chainMan.CurrentBlock()) { + if !bytes.Equal(chains[longest][len(chains[longest])-1].Hash(), chainMan.CurrentBlock().Hash()) { t.Error("Invalid canonical chain") } } + +func TestGetAncestors(t *testing.T) { + db, _ := ethdb.NewMemDatabase() + var eventMux event.TypeMux + chainMan := NewChainManager(db, &eventMux) + chain, err := loadChain("valid1", t) + if err != nil { + fmt.Println(err) + t.FailNow() + } + + for _, block := range chain { + chainMan.write(block) + } + + ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4) + fmt.Println(ancestors) +} diff --git a/core/execution.go b/core/execution.go index 43f4b58fb..cad4e84aa 100644 --- a/core/execution.go +++ b/core/execution.go @@ -5,6 +5,7 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) @@ -13,7 +14,6 @@ type Execution struct { env vm.Environment address, input []byte Gas, price, value *big.Int - SkipTransfer bool } func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution { @@ -33,7 +33,7 @@ func (self *Execution) Call(codeAddr []byte, caller vm.ContextRef) ([]byte, erro func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) { env := self.env - evm := vm.New(env, vm.DebugVmTy) + evm := vm.New(env) if env.Depth() == vm.MaxCallDepth { caller.ReturnGas(self.Gas, self.price) @@ -41,16 +41,22 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret return nil, vm.DepthError{} } + vsnapshot := env.State().Copy() + if len(self.address) == 0 { + // Generate a new address + nonce := env.State().GetNonce(caller.Address()) + self.address = crypto.CreateAddress(caller.Address(), nonce) + env.State().SetNonce(caller.Address(), nonce+1) + } + from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(self.address) - // Skipping transfer is used on testing for the initial call - if !self.SkipTransfer { - err = env.Transfer(from, to, self.value) - if err != nil { - caller.ReturnGas(self.Gas, self.price) - - err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, from.Balance) - return - } + err = env.Transfer(from, to, self.value) + if err != nil { + env.State().Set(vsnapshot) + + caller.ReturnGas(self.Gas, self.price) + + return nil, fmt.Errorf("insufficient funds to transfer value. Req %v, has %v", self.value, from.Balance()) } snapshot := env.State().Copy() diff --git a/core/genesis.go b/core/genesis.go index 10b40516f..d9edaace2 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -19,18 +19,20 @@ var ZeroHash512 = make([]byte, 64) var EmptyShaList = crypto.Sha3(ethutil.Encode([]interface{}{})) var EmptyListRoot = crypto.Sha3(ethutil.Encode("")) -func GenesisBlock() *types.Block { +func GenesisBlock(db ethutil.Database) *types.Block { genesis := types.NewBlock(ZeroHash256, ZeroHash160, nil, big.NewInt(131072), crypto.Sha3(big.NewInt(42).Bytes()), "") genesis.Header().Number = ethutil.Big0 genesis.Header().GasLimit = big.NewInt(1000000) genesis.Header().GasUsed = ethutil.Big0 genesis.Header().Time = 0 + genesis.Td = ethutil.Big0 genesis.SetUncles([]*types.Header{}) genesis.SetTransactions(types.Transactions{}) genesis.SetReceipts(types.Receipts{}) - statedb := state.New(genesis.Trie()) + statedb := state.New(genesis.Root(), db) + //statedb := state.New(genesis.Trie()) for _, addr := range []string{ "51ba59315b3a95761d0863b05ccc7a7f54703d99", "e4157b34ea9615cfbde6b4fda419828124b70c78", diff --git a/core/helper_test.go b/core/helper_test.go index b8bf254d7..7b41b86f1 100644 --- a/core/helper_test.go +++ b/core/helper_test.go @@ -77,7 +77,6 @@ func NewTestManager() *TestManager { fmt.Println("Could not create mem-db, failing") return nil } - ethutil.Config.Db = db testManager := &TestManager{} testManager.eventMux = new(event.TypeMux) diff --git a/core/state_transition.go b/core/state_transition.go index b22c5bf21..8b0ca2ac4 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -192,8 +192,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { if err == nil { dataGas := big.NewInt(int64(len(ret))) dataGas.Mul(dataGas, vm.GasCreateByte) - if err = self.UseGas(dataGas); err == nil { - //self.state.SetCode(ref.Address(), ret) + if err := self.UseGas(dataGas); err == nil { ref.SetCode(ret) } } diff --git a/core/transaction_pool.go b/core/transaction_pool.go index ff6c21aa9..d3aec9050 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -56,11 +56,6 @@ func NewTxPool(eventMux *event.TypeMux) *TxPool { } func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { - hash := tx.Hash() - if pool.txs[string(hash)] != nil { - return fmt.Errorf("Known transaction (%x)", hash[0:4]) - } - if len(tx.To()) != 0 && len(tx.To()) != 20 { return fmt.Errorf("Invalid recipient. len = %d", len(tx.To())) } @@ -97,6 +92,10 @@ func (self *TxPool) addTx(tx *types.Transaction) { } func (self *TxPool) Add(tx *types.Transaction) error { + if self.txs[string(tx.Hash())] != nil { + return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4]) + } + err := self.ValidateTransaction(tx) if err != nil { return err @@ -149,6 +148,7 @@ func (pool *TxPool) RemoveInvalid(query StateQuery) { for _, tx := range pool.txs { sender := query.GetAccount(tx.From()) err := pool.ValidateTransaction(tx) + fmt.Println(err, sender.Nonce, tx.Nonce()) if err != nil || sender.Nonce >= tx.Nonce() { removedTxs = append(removedTxs, tx) } diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go index e77d7a1ae..7f192fc4d 100644 --- a/core/transaction_pool_test.go +++ b/core/transaction_pool_test.go @@ -6,16 +6,22 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/state" ) // State query interface -type stateQuery struct{} +type stateQuery struct{ db ethutil.Database } + +func SQ() stateQuery { + db, _ := ethdb.NewMemDatabase() + return stateQuery{db: db} +} func (self stateQuery) GetAccount(addr []byte) *state.StateObject { - return state.NewStateObject(addr) + return state.NewStateObject(addr, self.db) } func transaction() *types.Transaction { @@ -55,7 +61,7 @@ func TestAddInvalidTx(t *testing.T) { func TestRemoveSet(t *testing.T) { pool, _ := setup() tx1 := transaction() - pool.pool.Add(tx1) + pool.addTx(tx1) pool.RemoveSet(types.Transactions{tx1}) if pool.Size() > 0 { t.Error("expected pool size to be 0") @@ -65,16 +71,16 @@ func TestRemoveSet(t *testing.T) { func TestRemoveInvalid(t *testing.T) { pool, key := setup() tx1 := transaction() - pool.pool.Add(tx1) - pool.RemoveInvalid(stateQuery{}) + pool.addTx(tx1) + pool.RemoveInvalid(SQ()) if pool.Size() > 0 { t.Error("expected pool size to be 0") } tx1.SetNonce(1) tx1.SignECDSA(key) - pool.pool.Add(tx1) - pool.RemoveInvalid(stateQuery{}) + pool.addTx(tx1) + pool.RemoveInvalid(SQ()) if pool.Size() != 1 { t.Error("expected pool size to be 1, is", pool.Size()) } diff --git a/core/types/block.go b/core/types/block.go index 7e19d003f..be57e86a6 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -9,9 +9,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/ptrie" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/state" ) type Header struct { @@ -168,16 +166,18 @@ func (self *Block) RlpDataForStorage() interface{} { } // Header accessors (add as you need them) -func (self *Block) Number() *big.Int { return self.header.Number } -func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } -func (self *Block) Bloom() []byte { return self.header.Bloom } -func (self *Block) Coinbase() []byte { return self.header.Coinbase } -func (self *Block) Time() int64 { return int64(self.header.Time) } -func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } -func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } -func (self *Block) Trie() *ptrie.Trie { return ptrie.New(self.header.Root, ethutil.Config.Db) } +func (self *Block) Number() *big.Int { return self.header.Number } +func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } +func (self *Block) Bloom() []byte { return self.header.Bloom } +func (self *Block) Coinbase() []byte { return self.header.Coinbase } +func (self *Block) Time() int64 { return int64(self.header.Time) } +func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } +func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } + +//func (self *Block) Trie() *ptrie.Trie { return ptrie.New(self.header.Root, ethutil.Config.Db) } +//func (self *Block) State() *state.StateDB { return state.New(self.Trie()) } +func (self *Block) Root() []byte { return self.header.Root } func (self *Block) SetRoot(root []byte) { self.header.Root = root } -func (self *Block) State() *state.StateDB { return state.New(self.Trie()) } func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) } // Implement pow.Block diff --git a/core/types/derive_sha.go b/core/types/derive_sha.go index 0beb19670..b2c442210 100644 --- a/core/types/derive_sha.go +++ b/core/types/derive_sha.go @@ -1,8 +1,9 @@ package types import ( + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/ptrie" + "github.com/ethereum/go-ethereum/trie" ) type DerivableList interface { @@ -11,7 +12,8 @@ type DerivableList interface { } func DeriveSha(list DerivableList) []byte { - trie := ptrie.New(nil, ethutil.Config.Db) + db, _ := ethdb.NewMemDatabase() + trie := trie.New(nil, db) for i := 0; i < list.Len(); i++ { trie.Update(ethutil.Encode(i), list.GetRlp(i)) } |