aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/block_processor.go104
-rw-r--r--core/chain_manager.go84
-rw-r--r--core/chain_manager_test.go46
-rw-r--r--core/execution.go28
-rw-r--r--core/genesis.go6
-rw-r--r--core/helper_test.go1
-rw-r--r--core/state_transition.go3
-rw-r--r--core/transaction_pool.go10
-rw-r--r--core/transaction_pool_test.go20
-rw-r--r--core/types/block.go22
-rw-r--r--core/types/derive_sha.go6
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))
}