aboutsummaryrefslogtreecommitdiffstats
path: root/chain
diff options
context:
space:
mode:
Diffstat (limited to 'chain')
-rw-r--r--chain/block_manager.go38
-rw-r--r--chain/chain_manager.go337
-rw-r--r--chain/chain_manager_test.go115
-rw-r--r--chain/dagger.go5
-rw-r--r--chain/events.go8
-rw-r--r--chain/filter.go9
-rw-r--r--chain/filter_test.go8
-rw-r--r--chain/helper_test.go19
-rw-r--r--chain/state_transition.go11
-rw-r--r--chain/transaction_pool.go41
-rw-r--r--chain/transaction_test.go1
-rw-r--r--chain/types/block.go (renamed from chain/block.go)4
-rw-r--r--chain/types/bloom9.go (renamed from chain/bloom9.go)2
-rw-r--r--chain/types/bloom9_test.go (renamed from chain/bloom9_test.go)6
-rw-r--r--chain/types/common.go10
-rw-r--r--chain/types/derive_sha.go (renamed from chain/derive_sha.go)2
-rw-r--r--chain/types/receipt.go (renamed from chain/receipt.go)10
-rw-r--r--chain/types/transaction.go (renamed from chain/transaction.go)2
-rw-r--r--chain/types/transaction_test.go1
-rw-r--r--chain/vm_env.go7
20 files changed, 382 insertions, 254 deletions
diff --git a/chain/block_manager.go b/chain/block_manager.go
index fdb221cc3..4cc43840c 100644
--- a/chain/block_manager.go
+++ b/chain/block_manager.go
@@ -9,6 +9,7 @@ import (
"sync"
"time"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
@@ -69,7 +70,7 @@ type BlockManager struct {
// The last attempted block is mainly used for debugging purposes
// This does not have to be a valid block and will be set during
// 'Process' & canonical validation.
- lastAttemptedBlock *Block
+ lastAttemptedBlock *types.Block
events event.Subscription
}
@@ -117,11 +118,11 @@ func (sm *BlockManager) ChainManager() *ChainManager {
return sm.bc
}
-func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state *state.State, block, parent *Block, txs Transactions) (Receipts, Transactions, Transactions, Transactions, error) {
+func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state *state.State, block, parent *types.Block, txs types.Transactions) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) {
var (
- receipts Receipts
- handled, unhandled Transactions
- erroneous Transactions
+ receipts types.Receipts
+ handled, unhandled types.Transactions
+ erroneous types.Transactions
totalUsedGas = big.NewInt(0)
err error
)
@@ -160,8 +161,9 @@ done:
state.Update(txGas)
cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
- receipt := &Receipt{ethutil.CopyBytes(state.Root()), cumulative, nil /*bloom*/, state.Logs()}
- receipt.Bloom = CreateBloom(Receipts{receipt})
+ receipt := types.NewReceipt(state.Root(), cumulative)
+ receipt.SetLogs(state.Logs())
+ receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
// Notify all subscribers
go self.eth.EventMux().Post(TxPostEvent{tx})
@@ -179,7 +181,7 @@ done:
return receipts, handled, unhandled, erroneous, err
}
-func (sm *BlockManager) Process(block *Block) (td *big.Int, msgs state.Messages, err error) {
+func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Messages, err error) {
// Processing a blocks may never happen simultaneously
sm.mutex.Lock()
defer sm.mutex.Unlock()
@@ -196,7 +198,7 @@ func (sm *BlockManager) Process(block *Block) (td *big.Int, msgs state.Messages,
return sm.ProcessWithParent(block, parent)
}
-func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, messages state.Messages, err error) {
+func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) {
sm.lastAttemptedBlock = block
state := parent.State().Copy()
@@ -216,13 +218,13 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me
return
}
- txSha := DeriveSha(block.transactions)
+ txSha := types.DeriveSha(block.Transactions())
if bytes.Compare(txSha, block.TxSha) != 0 {
err = fmt.Errorf("validating transaction root. received=%x got=%x", block.TxSha, txSha)
return
}
- receiptSha := DeriveSha(receipts)
+ receiptSha := types.DeriveSha(receipts)
if bytes.Compare(receiptSha, block.ReceiptSha) != 0 {
err = fmt.Errorf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha)
return
@@ -239,8 +241,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me
return
}
- block.receipts = receipts // although this isn't necessary it be in the future
- rbloom := CreateBloom(receipts)
+ //block.receipts = receipts // although this isn't necessary it be in the future
+ rbloom := types.CreateBloom(receipts)
if bytes.Compare(rbloom, block.LogsBloom) != 0 {
err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
return
@@ -273,7 +275,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me
}
}
-func (sm *BlockManager) ApplyDiff(state *state.State, parent, block *Block) (receipts Receipts, err error) {
+func (sm *BlockManager) ApplyDiff(state *state.State, parent, block *types.Block) (receipts types.Receipts, err error) {
coinbase := state.GetOrNewStateObject(block.Coinbase)
coinbase.SetGasPool(block.CalcGasLimit(parent))
@@ -286,7 +288,7 @@ func (sm *BlockManager) ApplyDiff(state *state.State, parent, block *Block) (rec
return receipts, nil
}
-func (sm *BlockManager) CalculateTD(block *Block) (*big.Int, bool) {
+func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) {
uncleDiff := new(big.Int)
for _, uncle := range block.Uncles {
uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
@@ -312,7 +314,7 @@ func (sm *BlockManager) CalculateTD(block *Block) (*big.Int, bool) {
// 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 *BlockManager) ValidateBlock(block, parent *Block) error {
+func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
expd := CalcDifficulty(block, parent)
if expd.Cmp(block.Difficulty) < 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
@@ -338,7 +340,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *Block) error {
return nil
}
-func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *Block) error {
+func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *types.Block) error {
reward := new(big.Int).Set(BlockReward)
knownUncles := ethutil.Set(parent.Uncles)
@@ -381,7 +383,7 @@ func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *Blo
return nil
}
-func (sm *BlockManager) GetMessages(block *Block) (messages []*state.Message, err error) {
+func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error) {
if !sm.bc.HasBlock(block.PrevHash) {
return nil, ParentError(block.PrevHash)
}
diff --git a/chain/chain_manager.go b/chain/chain_manager.go
index 0c3a7a928..115acb1c8 100644
--- a/chain/chain_manager.go
+++ b/chain/chain_manager.go
@@ -6,6 +6,7 @@ import (
"fmt"
"math/big"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
@@ -13,36 +14,88 @@ import (
var chainlogger = logger.NewLogger("CHAIN")
+func AddTestNetFunds(block *types.Block) {
+ for _, addr := range []string{
+ "51ba59315b3a95761d0863b05ccc7a7f54703d99",
+ "e4157b34ea9615cfbde6b4fda419828124b70c78",
+ "b9c015918bdaba24b4ff057a92a3873d6eb201be",
+ "6c386a4b26f73c802f34673f7248bb118f97424a",
+ "cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
+ "2ef47100e0787b915105fd5e3f4ff6752079d5cb",
+ "e6716f9544a56c530d868e4bfbacb172315bdead",
+ "1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
+ } {
+ codedAddr := ethutil.Hex2Bytes(addr)
+ account := block.State().GetAccount(codedAddr)
+ account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200)
+ block.State().UpdateStateObject(account)
+ }
+}
+
+func CalcDifficulty(block, parent *types.Block) *big.Int {
+ diff := new(big.Int)
+
+ adjust := new(big.Int).Rsh(parent.Difficulty, 10)
+ if block.Time >= parent.Time+5 {
+ diff.Sub(parent.Difficulty, adjust)
+ } else {
+ diff.Add(parent.Difficulty, adjust)
+ }
+
+ return diff
+}
+
type ChainManager struct {
- Ethereum EthManager
- // The famous, the fabulous Mister GENESIIIIIIS (block)
- genesisBlock *Block
+ //eth EthManager
+ processor types.BlockProcessor
+ genesisBlock *types.Block
// Last known total difficulty
TD *big.Int
LastBlockNumber uint64
- CurrentBlock *Block
+ CurrentBlock *types.Block
LastBlockHash []byte
workingChain *BlockChain
}
-func NewChainManager(ethereum EthManager) *ChainManager {
+func NewChainManager() *ChainManager {
bc := &ChainManager{}
- bc.genesisBlock = NewBlockFromBytes(ethutil.Encode(Genesis))
- bc.Ethereum = ethereum
+ bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis))
+ //bc.eth = ethereum
bc.setLastBlock()
return bc
}
-func (bc *ChainManager) Genesis() *Block {
- return bc.genesisBlock
+func (self *ChainManager) SetProcessor(proc types.BlockProcessor) {
+ self.processor = proc
}
-func (bc *ChainManager) NewBlock(coinbase []byte) *Block {
+func (bc *ChainManager) setLastBlock() {
+ data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
+ if len(data) != 0 {
+ // Prep genesis
+ AddTestNetFunds(bc.genesisBlock)
+
+ block := types.NewBlockFromBytes(data)
+ bc.CurrentBlock = block
+ bc.LastBlockHash = block.Hash()
+ bc.LastBlockNumber = block.Number.Uint64()
+
+ // Set the last know difficulty (might be 0x0 as initial value, Genesis)
+ bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
+ } else {
+ bc.Reset()
+ }
+
+ chainlogger.Infof("Last block (#%d) %x\n", bc.LastBlockNumber, bc.CurrentBlock.Hash())
+}
+
+// Block creation & chain handling
+func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block {
var root interface{}
hash := ZeroHash256
@@ -51,7 +104,7 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *Block {
hash = bc.LastBlockHash
}
- block := CreateBlock(
+ block := types.CreateBlock(
root,
hash,
coinbase,
@@ -70,23 +123,10 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *Block {
return block
}
-func CalcDifficulty(block, parent *Block) *big.Int {
- diff := new(big.Int)
-
- adjust := new(big.Int).Rsh(parent.Difficulty, 10)
- if block.Time >= parent.Time+5 {
- diff.Sub(parent.Difficulty, adjust)
- } else {
- diff.Add(parent.Difficulty, adjust)
- }
-
- return diff
-}
-
func (bc *ChainManager) Reset() {
AddTestNetFunds(bc.genesisBlock)
- bc.genesisBlock.state.Trie.Sync()
+ bc.genesisBlock.Trie().Sync()
// Prepare the genesis block
bc.add(bc.genesisBlock)
bc.CurrentBlock = bc.genesisBlock
@@ -97,38 +137,31 @@ func (bc *ChainManager) Reset() {
bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
}
-func (bc *ChainManager) HasBlock(hash []byte) bool {
- data, _ := ethutil.Config.Db.Get(hash)
- return len(data) != 0
-}
-
-// TODO: At one point we might want to save a block by prevHash in the db to optimise this...
-func (bc *ChainManager) HasBlockWithPrevHash(hash []byte) bool {
- block := bc.CurrentBlock
-
- for ; block != nil; block = bc.GetBlock(block.PrevHash) {
- if bytes.Compare(hash, block.PrevHash) == 0 {
- return true
- }
- }
- return false
-}
+// Add a block to the chain and record addition information
+func (bc *ChainManager) add(block *types.Block) {
+ bc.writeBlockInfo(block)
-func (bc *ChainManager) CalculateBlockTD(block *Block) *big.Int {
- blockDiff := new(big.Int)
+ bc.CurrentBlock = block
+ bc.LastBlockHash = block.Hash()
- for _, uncle := range block.Uncles {
- blockDiff = blockDiff.Add(blockDiff, uncle.Difficulty)
- }
- blockDiff = blockDiff.Add(blockDiff, block.Difficulty)
+ encodedBlock := block.RlpEncode()
+ ethutil.Config.Db.Put(block.Hash(), encodedBlock)
+ ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock)
- return blockDiff
+ //chainlogger.Infof("Imported block #%d (%x...)\n", block.Number, block.Hash()[0:4])
}
-func (bc *ChainManager) GenesisBlock() *Block {
+// Accessors
+func (bc *ChainManager) Genesis() *types.Block {
return bc.genesisBlock
}
+// Block fetching methods
+func (bc *ChainManager) HasBlock(hash []byte) bool {
+ data, _ := ethutil.Config.Db.Get(hash)
+ return len(data) != 0
+}
+
func (self *ChainManager) GetChainHashesFromHash(hash []byte, max uint64) (chain [][]byte) {
block := self.GetBlock(hash)
if block == nil {
@@ -150,91 +183,14 @@ func (self *ChainManager) GetChainHashesFromHash(hash []byte, max uint64) (chain
return
}
-func AddTestNetFunds(block *Block) {
- for _, addr := range []string{
- "51ba59315b3a95761d0863b05ccc7a7f54703d99",
- "e4157b34ea9615cfbde6b4fda419828124b70c78",
- "b9c015918bdaba24b4ff057a92a3873d6eb201be",
- "6c386a4b26f73c802f34673f7248bb118f97424a",
- "cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
- "2ef47100e0787b915105fd5e3f4ff6752079d5cb",
- "e6716f9544a56c530d868e4bfbacb172315bdead",
- "1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
- } {
- codedAddr := ethutil.Hex2Bytes(addr)
- account := block.state.GetAccount(codedAddr)
- account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200)
- block.state.UpdateStateObject(account)
- }
-}
-
-func (bc *ChainManager) setLastBlock() {
- data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
- if len(data) != 0 {
- // Prep genesis
- AddTestNetFunds(bc.genesisBlock)
-
- block := NewBlockFromBytes(data)
- bc.CurrentBlock = block
- bc.LastBlockHash = block.Hash()
- bc.LastBlockNumber = block.Number.Uint64()
-
- // Set the last know difficulty (might be 0x0 as initial value, Genesis)
- bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
- } else {
- bc.Reset()
- }
-
- chainlogger.Infof("Last block (#%d) %x\n", bc.LastBlockNumber, bc.CurrentBlock.Hash())
-}
-
-func (bc *ChainManager) SetTotalDifficulty(td *big.Int) {
- ethutil.Config.Db.Put([]byte("LTD"), td.Bytes())
- bc.TD = td
-}
-
-// Add a block to the chain and record addition information
-func (bc *ChainManager) add(block *Block) {
- bc.writeBlockInfo(block)
-
- bc.CurrentBlock = block
- bc.LastBlockHash = block.Hash()
-
- encodedBlock := block.RlpEncode()
- ethutil.Config.Db.Put(block.Hash(), encodedBlock)
- ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock)
-
- //chainlogger.Infof("Imported block #%d (%x...)\n", block.Number, block.Hash()[0:4])
-}
-
-func (self *ChainManager) CalcTotalDiff(block *Block) (*big.Int, error) {
- parent := self.GetBlock(block.PrevHash)
- if parent == nil {
- return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash)
- }
-
- parentTd := parent.BlockInfo().TD
-
- uncleDiff := new(big.Int)
- for _, uncle := range block.Uncles {
- uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
- }
-
- td := new(big.Int)
- td = td.Add(parentTd, uncleDiff)
- td = td.Add(td, block.Difficulty)
-
- return td, nil
-}
-
-func (self *ChainManager) GetBlock(hash []byte) *Block {
+func (self *ChainManager) GetBlock(hash []byte) *types.Block {
data, _ := ethutil.Config.Db.Get(hash)
if len(data) == 0 {
if self.workingChain != nil {
// Check the temp chain
for e := self.workingChain.Front(); e != nil; e = e.Next() {
- if bytes.Compare(e.Value.(*link).block.Hash(), hash) == 0 {
- return e.Value.(*link).block
+ if bytes.Compare(e.Value.(*link).Block.Hash(), hash) == 0 {
+ return e.Value.(*link).Block
}
}
}
@@ -242,10 +198,10 @@ func (self *ChainManager) GetBlock(hash []byte) *Block {
return nil
}
- return NewBlockFromBytes(data)
+ return types.NewBlockFromBytes(data)
}
-func (self *ChainManager) GetBlockByNumber(num uint64) *Block {
+func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
block := self.CurrentBlock
for ; block != nil; block = self.GetBlock(block.PrevHash) {
if block.Number.Uint64() == num {
@@ -260,26 +216,33 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *Block {
return block
}
-func (self *ChainManager) GetBlockBack(num uint64) *Block {
- block := self.CurrentBlock
+func (bc *ChainManager) SetTotalDifficulty(td *big.Int) {
+ ethutil.Config.Db.Put([]byte("LTD"), td.Bytes())
+ bc.TD = td
+}
- for ; num != 0 && block != nil; num-- {
- block = self.GetBlock(block.PrevHash)
+func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
+ parent := self.GetBlock(block.PrevHash)
+ if parent == nil {
+ return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash)
}
- return block
-}
+ parentTd := parent.BlockInfo().TD
-func (bc *ChainManager) BlockInfoByHash(hash []byte) BlockInfo {
- bi := BlockInfo{}
- data, _ := ethutil.Config.Db.Get(append(hash, []byte("Info")...))
- bi.RlpDecode(data)
+ uncleDiff := new(big.Int)
+ for _, uncle := range block.Uncles {
+ uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
+ }
- return bi
+ td := new(big.Int)
+ td = td.Add(parentTd, uncleDiff)
+ td = td.Add(td, block.Difficulty)
+
+ return td, nil
}
-func (bc *ChainManager) BlockInfo(block *Block) BlockInfo {
- bi := BlockInfo{}
+func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo {
+ bi := types.BlockInfo{}
data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...))
bi.RlpDecode(data)
@@ -287,9 +250,9 @@ func (bc *ChainManager) BlockInfo(block *Block) BlockInfo {
}
// Unexported method for writing extra non-essential block info to the db
-func (bc *ChainManager) writeBlockInfo(block *Block) {
+func (bc *ChainManager) writeBlockInfo(block *types.Block) {
bc.LastBlockNumber++
- bi := BlockInfo{Number: bc.LastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.TD}
+ bi := types.BlockInfo{Number: bc.LastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.TD}
// For now we use the block hash with the words "info" appended as key
ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode())
@@ -301,40 +264,24 @@ func (bc *ChainManager) Stop() {
}
}
-type link struct {
- block *Block
- messages state.Messages
- td *big.Int
-}
-
-type BlockChain struct {
- *list.List
-}
-
-func NewChain(blocks Blocks) *BlockChain {
- chain := &BlockChain{list.New()}
-
- for _, block := range blocks {
- chain.PushBack(&link{block, nil, nil})
- }
-
- return chain
+func (self *ChainManager) NewIterator(startHash []byte) *ChainIterator {
+ return &ChainIterator{self, self.GetBlock(startHash)}
}
// This function assumes you've done your checking. No checking is done at this stage anymore
-func (self *ChainManager) InsertChain(chain *BlockChain) {
+func (self *ChainManager) InsertChain(chain *BlockChain, call func(*types.Block, state.Messages)) {
for e := chain.Front(); e != nil; e = e.Next() {
link := e.Value.(*link)
- self.add(link.block)
- self.SetTotalDifficulty(link.td)
- self.Ethereum.EventMux().Post(NewBlockEvent{link.block})
- self.Ethereum.EventMux().Post(link.messages)
+ self.add(link.Block)
+ self.SetTotalDifficulty(link.Td)
+
+ call(link.Block, link.Messages)
}
b, e := chain.Front(), chain.Back()
if b != nil && e != nil {
- front, back := b.Value.(*link).block, e.Value.(*link).block
+ front, back := b.Value.(*link).Block, e.Value.(*link).Block
chainlogger.Infof("Imported %d blocks. #%v (%x) / %#v (%x)", chain.Len(), front.Number, front.Hash()[0:4], back.Number, back.Hash()[0:4])
}
}
@@ -346,20 +293,17 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error)
for e := chain.Front(); e != nil; e = e.Next() {
var (
l = e.Value.(*link)
- block = l.block
+ block = l.Block
parent = self.GetBlock(block.PrevHash)
)
- //fmt.Println("parent", parent)
- //fmt.Println("current", block)
-
if parent == nil {
err = fmt.Errorf("incoming chain broken on hash %x\n", block.PrevHash[0:4])
return
}
var messages state.Messages
- td, messages, err = self.Ethereum.BlockManager().ProcessWithParent(block, parent)
+ td, messages, err = self.processor.ProcessWithParent(block, parent) //self.eth.BlockManager().ProcessWithParent(block, parent)
if err != nil {
chainlogger.Infoln(err)
chainlogger.Debugf("Block #%v failed (%x...)\n", block.Number, block.Hash()[0:4])
@@ -368,8 +312,8 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error)
err = fmt.Errorf("incoming chain failed %v\n", err)
return
}
- l.td = td
- l.messages = messages
+ l.Td = td
+ l.Messages = messages
}
if td.Cmp(self.TD) <= 0 {
@@ -381,3 +325,42 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error)
return
}
+
+type link struct {
+ Block *types.Block
+ Messages state.Messages
+ Td *big.Int
+}
+
+type BlockChain struct {
+ *list.List
+}
+
+func NewChain(blocks types.Blocks) *BlockChain {
+ chain := &BlockChain{list.New()}
+
+ for _, block := range blocks {
+ chain.PushBack(&link{block, nil, nil})
+ }
+
+ return chain
+}
+
+func (self *BlockChain) RlpEncode() []byte {
+ dat := make([]interface{}, 0)
+ for e := self.Front(); e != nil; e = e.Next() {
+ dat = append(dat, e.Value.(*link).Block.RlpData())
+ }
+
+ return ethutil.Encode(dat)
+}
+
+type ChainIterator struct {
+ cm *ChainManager
+ block *types.Block // current block in the iterator
+}
+
+func (self *ChainIterator) Prev() *types.Block {
+ self.block = self.cm.GetBlock(self.block.PrevHash)
+ return self.block
+}
diff --git a/chain/chain_manager_test.go b/chain/chain_manager_test.go
index fef1d2010..0314914a9 100644
--- a/chain/chain_manager_test.go
+++ b/chain/chain_manager_test.go
@@ -1 +1,116 @@
package chain
+
+import (
+ "fmt"
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/chain/types"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/state"
+)
+
+var TD *big.Int
+
+func init() {
+ ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
+ ethutil.Config.Db, _ = ethdb.NewMemDatabase()
+}
+
+type fakeproc struct {
+}
+
+func (self fakeproc) ProcessWithParent(a, b *types.Block) (*big.Int, state.Messages, error) {
+ TD = new(big.Int).Add(TD, big.NewInt(1))
+ return TD, nil, nil
+}
+
+func makechain(cman *ChainManager, max int) *BlockChain {
+ blocks := make(types.Blocks, max)
+ for i := 0; i < max; i++ {
+ addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
+ block := cman.NewBlock(addr)
+ if i != 0 {
+ cman.CurrentBlock = blocks[i-1]
+ }
+ blocks[i] = block
+ }
+ return NewChain(blocks)
+}
+
+func TestLongerFork(t *testing.T) {
+ cman := NewChainManager()
+ cman.SetProcessor(fakeproc{})
+
+ TD = big.NewInt(1)
+ chainA := makechain(cman, 5)
+
+ TD = big.NewInt(1)
+ chainB := makechain(cman, 10)
+
+ td, err := cman.TestChain(chainA)
+ if err != nil {
+ t.Error("unable to create new TD from chainA:", err)
+ }
+ cman.TD = td
+
+ _, err = cman.TestChain(chainB)
+ if err != nil {
+ t.Error("expected chainB not to give errors:", err)
+ }
+}
+
+func TestEqualFork(t *testing.T) {
+ cman := NewChainManager()
+ cman.SetProcessor(fakeproc{})
+
+ TD = big.NewInt(1)
+ chainA := makechain(cman, 5)
+
+ TD = big.NewInt(2)
+ chainB := makechain(cman, 5)
+
+ td, err := cman.TestChain(chainA)
+ if err != nil {
+ t.Error("unable to create new TD from chainA:", err)
+ }
+ cman.TD = td
+
+ _, err = cman.TestChain(chainB)
+ if err != nil {
+ t.Error("expected chainB not to give errors:", err)
+ }
+}
+
+func TestBrokenChain(t *testing.T) {
+ cman := NewChainManager()
+ cman.SetProcessor(fakeproc{})
+
+ TD = big.NewInt(1)
+ chain := makechain(cman, 5)
+ chain.Remove(chain.Front())
+
+ _, err := cman.TestChain(chain)
+ if err == nil {
+ t.Error("expected broken chain to return error")
+ }
+}
+
+func BenchmarkChainTesting(b *testing.B) {
+ const chainlen = 1000
+
+ ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
+ ethutil.Config.Db, _ = ethdb.NewMemDatabase()
+
+ cman := NewChainManager()
+ cman.SetProcessor(fakeproc{})
+
+ TD = big.NewInt(1)
+ chain := makechain(cman, chainlen)
+
+ stime := time.Now()
+ cman.TestChain(chain)
+ fmt.Println(chainlen, "took", time.Since(stime))
+}
diff --git a/chain/dagger.go b/chain/dagger.go
index 2cf70e091..f7e2229e9 100644
--- a/chain/dagger.go
+++ b/chain/dagger.go
@@ -6,6 +6,7 @@ import (
"math/rand"
"time"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
@@ -15,7 +16,7 @@ import (
var powlogger = logger.NewLogger("POW")
type PoW interface {
- Search(block *Block, stop <-chan struct{}) []byte
+ Search(block *types.Block, stop <-chan struct{}) []byte
Verify(hash []byte, diff *big.Int, nonce []byte) bool
GetHashrate() int64
Turbo(bool)
@@ -35,7 +36,7 @@ func (pow *EasyPow) Turbo(on bool) {
pow.turbo = on
}
-func (pow *EasyPow) Search(block *Block, stop <-chan struct{}) []byte {
+func (pow *EasyPow) Search(block *types.Block, stop <-chan struct{}) []byte {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
hash := block.HashNoNonce()
diff := block.Difficulty
diff --git a/chain/events.go b/chain/events.go
index 2703e955d..06ab6be79 100644
--- a/chain/events.go
+++ b/chain/events.go
@@ -1,10 +1,12 @@
package chain
+import "github.com/ethereum/go-ethereum/chain/types"
+
// TxPreEvent is posted when a transaction enters the transaction pool.
-type TxPreEvent struct{ Tx *Transaction }
+type TxPreEvent struct{ Tx *types.Transaction }
// TxPostEvent is posted when a transaction has been processed.
-type TxPostEvent struct{ Tx *Transaction }
+type TxPostEvent struct{ Tx *types.Transaction }
// NewBlockEvent is posted when a block has been imported.
-type NewBlockEvent struct{ Block *Block }
+type NewBlockEvent struct{ Block *types.Block }
diff --git a/chain/filter.go b/chain/filter.go
index 3c0b02d4f..fd8adaa8f 100644
--- a/chain/filter.go
+++ b/chain/filter.go
@@ -5,6 +5,7 @@ import (
"math"
"math/big"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/state"
)
@@ -24,7 +25,7 @@ type Filter struct {
Altered []AccountChange
- BlockCallback func(*Block)
+ BlockCallback func(*types.Block)
MessageCallback func(state.Messages)
}
@@ -171,11 +172,11 @@ func (self *Filter) FilterMessages(msgs []*state.Message) []*state.Message {
return messages
}
-func (self *Filter) bloomFilter(block *Block) bool {
+func (self *Filter) bloomFilter(block *types.Block) bool {
var fromIncluded, toIncluded bool
if len(self.from) > 0 {
for _, from := range self.from {
- if BloomLookup(block.LogsBloom, from) {
+ if types.BloomLookup(block.LogsBloom, from) {
fromIncluded = true
break
}
@@ -186,7 +187,7 @@ func (self *Filter) bloomFilter(block *Block) bool {
if len(self.to) > 0 {
for _, to := range self.to {
- if BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) {
+ if types.BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) {
toIncluded = true
break
}
diff --git a/chain/filter_test.go b/chain/filter_test.go
index abfbf4b87..c63bb5a2d 100644
--- a/chain/filter_test.go
+++ b/chain/filter_test.go
@@ -1,7 +1,7 @@
package chain
-import "testing"
+// import "testing"
-func TestFilter(t *testing.T) {
- NewFilter(NewTestManager())
-}
+// func TestFilter(t *testing.T) {
+// NewFilter(NewTestManager())
+// }
diff --git a/chain/helper_test.go b/chain/helper_test.go
index 642d19c95..8c7532111 100644
--- a/chain/helper_test.go
+++ b/chain/helper_test.go
@@ -4,6 +4,7 @@ import (
"container/list"
"fmt"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
@@ -13,13 +14,13 @@ import (
// Implement our EthTest Manager
type TestManager struct {
- stateManager *StateManager
- eventMux *event.TypeMux
+ // stateManager *StateManager
+ eventMux *event.TypeMux
db ethutil.Database
txPool *TxPool
blockChain *ChainManager
- Blocks []*Block
+ Blocks []*types.Block
}
func (s *TestManager) IsListening() bool {
@@ -46,9 +47,9 @@ func (tm *TestManager) TxPool() *TxPool {
return tm.txPool
}
-func (tm *TestManager) StateManager() *StateManager {
- return tm.stateManager
-}
+// func (tm *TestManager) StateManager() *StateManager {
+// return tm.stateManager
+// }
func (tm *TestManager) EventMux() *event.TypeMux {
return tm.eventMux
@@ -81,9 +82,9 @@ func NewTestManager() *TestManager {
testManager := &TestManager{}
testManager.eventMux = new(event.TypeMux)
testManager.db = db
- testManager.txPool = NewTxPool(testManager)
- testManager.blockChain = NewChainManager(testManager)
- testManager.stateManager = NewStateManager(testManager)
+ // testManager.txPool = NewTxPool(testManager)
+ // testManager.blockChain = NewChainManager(testManager)
+ // testManager.stateManager = NewStateManager(testManager)
// Start the tx pool
testManager.txPool.Start()
diff --git a/chain/state_transition.go b/chain/state_transition.go
index f9b82c58b..53b1f6e2d 100644
--- a/chain/state_transition.go
+++ b/chain/state_transition.go
@@ -4,6 +4,7 @@ import (
"fmt"
"math/big"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
)
@@ -26,17 +27,17 @@ import (
*/
type StateTransition struct {
coinbase, receiver []byte
- tx *Transaction
+ tx *types.Transaction
gas, gasPrice *big.Int
value *big.Int
data []byte
state *state.State
- block *Block
+ block *types.Block
cb, rec, sen *state.StateObject
}
-func NewStateTransition(coinbase *state.StateObject, tx *Transaction, state *state.State, block *Block) *StateTransition {
+func NewStateTransition(coinbase *state.StateObject, tx *types.Transaction, state *state.State, block *types.Block) *StateTransition {
return &StateTransition{coinbase.Address(), tx.Recipient, tx, new(big.Int), new(big.Int).Set(tx.GasPrice), tx.Value, tx.Data, state, block, coinbase, nil, nil}
}
@@ -215,7 +216,7 @@ func (self *StateTransition) TransitionState() (err error) {
})
// Process the init code and create 'valid' contract
- if IsContractAddr(self.receiver) {
+ if types.IsContractAddr(self.receiver) {
// Evaluate the initialization script
// and use the return value as the
// script section for the state object.
@@ -292,7 +293,7 @@ func (self *StateTransition) Eval(msg *state.Message, script []byte, context *st
}
// Converts an transaction in to a state object
-func MakeContract(tx *Transaction, state *state.State) *state.StateObject {
+func MakeContract(tx *types.Transaction, state *state.State) *state.StateObject {
addr := tx.CreationAddress(state)
contract := state.GetOrNewStateObject(addr)
diff --git a/chain/transaction_pool.go b/chain/transaction_pool.go
index ff75089d6..119712ba8 100644
--- a/chain/transaction_pool.go
+++ b/chain/transaction_pool.go
@@ -7,6 +7,7 @@ import (
"math/big"
"sync"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/wire"
@@ -16,7 +17,7 @@ var txplogger = logger.NewLogger("TXP")
const txPoolQueueSize = 50
-type TxPoolHook chan *Transaction
+type TxPoolHook chan *types.Transaction
type TxMsgTy byte
const (
@@ -26,21 +27,21 @@ const (
var MinGasPrice = big.NewInt(10000000000000)
type TxMsg struct {
- Tx *Transaction
+ Tx *types.Transaction
Type TxMsgTy
}
-func EachTx(pool *list.List, it func(*Transaction, *list.Element) bool) {
+func EachTx(pool *list.List, it func(*types.Transaction, *list.Element) bool) {
for e := pool.Front(); e != nil; e = e.Next() {
- if it(e.Value.(*Transaction), e) {
+ if it(e.Value.(*types.Transaction), e) {
break
}
}
}
-func FindTx(pool *list.List, finder func(*Transaction, *list.Element) bool) *Transaction {
+func FindTx(pool *list.List, finder func(*types.Transaction, *list.Element) bool) *types.Transaction {
for e := pool.Front(); e != nil; e = e.Next() {
- if tx, ok := e.Value.(*Transaction); ok {
+ if tx, ok := e.Value.(*types.Transaction); ok {
if finder(tx, e) {
return tx
}
@@ -51,7 +52,7 @@ func FindTx(pool *list.List, finder func(*Transaction, *list.Element) bool) *Tra
}
type TxProcessor interface {
- ProcessTransaction(tx *Transaction)
+ ProcessTransaction(tx *types.Transaction)
}
// The tx pool a thread safe transaction pool handler. In order to
@@ -65,7 +66,7 @@ type TxPool struct {
mutex sync.Mutex
// Queueing channel for reading and writing incoming
// transactions to
- queueChan chan *Transaction
+ queueChan chan *types.Transaction
// Quiting channel
quit chan bool
// The actual pool
@@ -79,14 +80,14 @@ type TxPool struct {
func NewTxPool(ethereum EthManager) *TxPool {
return &TxPool{
pool: list.New(),
- queueChan: make(chan *Transaction, txPoolQueueSize),
+ queueChan: make(chan *types.Transaction, txPoolQueueSize),
quit: make(chan bool),
Ethereum: ethereum,
}
}
// Blocking function. Don't use directly. Use QueueTransaction instead
-func (pool *TxPool) addTransaction(tx *Transaction) {
+func (pool *TxPool) addTransaction(tx *types.Transaction) {
pool.mutex.Lock()
defer pool.mutex.Unlock()
@@ -96,7 +97,7 @@ func (pool *TxPool) addTransaction(tx *Transaction) {
pool.Ethereum.Broadcast(wire.MsgTxTy, []interface{}{tx.RlpData()})
}
-func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
+func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
// Get the last block so we can retrieve the sender and receiver from
// the merkle trie
block := pool.Ethereum.ChainManager().CurrentBlock
@@ -142,7 +143,7 @@ out:
select {
case tx := <-pool.queueChan:
hash := tx.Hash()
- foundTx := FindTx(pool.pool, func(tx *Transaction, e *list.Element) bool {
+ foundTx := FindTx(pool.pool, func(tx *types.Transaction, e *list.Element) bool {
return bytes.Compare(tx.Hash(), hash) == 0
})
@@ -172,18 +173,18 @@ out:
}
}
-func (pool *TxPool) QueueTransaction(tx *Transaction) {
+func (pool *TxPool) QueueTransaction(tx *types.Transaction) {
pool.queueChan <- tx
}
-func (pool *TxPool) CurrentTransactions() []*Transaction {
+func (pool *TxPool) CurrentTransactions() []*types.Transaction {
pool.mutex.Lock()
defer pool.mutex.Unlock()
- txList := make([]*Transaction, pool.pool.Len())
+ txList := make([]*types.Transaction, pool.pool.Len())
i := 0
for e := pool.pool.Front(); e != nil; e = e.Next() {
- tx := e.Value.(*Transaction)
+ tx := e.Value.(*types.Transaction)
txList[i] = tx
@@ -198,7 +199,7 @@ func (pool *TxPool) RemoveInvalid(state *state.State) {
defer pool.mutex.Unlock()
for e := pool.pool.Front(); e != nil; e = e.Next() {
- tx := e.Value.(*Transaction)
+ tx := e.Value.(*types.Transaction)
sender := state.GetAccount(tx.Sender())
err := pool.ValidateTransaction(tx)
if err != nil || sender.Nonce >= tx.Nonce {
@@ -207,12 +208,12 @@ func (pool *TxPool) RemoveInvalid(state *state.State) {
}
}
-func (self *TxPool) RemoveSet(txs Transactions) {
+func (self *TxPool) RemoveSet(txs types.Transactions) {
self.mutex.Lock()
defer self.mutex.Unlock()
for _, tx := range txs {
- EachTx(self.pool, func(t *Transaction, element *list.Element) bool {
+ EachTx(self.pool, func(t *types.Transaction, element *list.Element) bool {
if t == tx {
self.pool.Remove(element)
return true // To stop the loop
@@ -222,7 +223,7 @@ func (self *TxPool) RemoveSet(txs Transactions) {
}
}
-func (pool *TxPool) Flush() []*Transaction {
+func (pool *TxPool) Flush() []*types.Transaction {
txList := pool.CurrentTransactions()
// Recreate a new list all together
diff --git a/chain/transaction_test.go b/chain/transaction_test.go
deleted file mode 100644
index fef1d2010..000000000
--- a/chain/transaction_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package chain
diff --git a/chain/block.go b/chain/types/block.go
index dccb7ca41..5c8bb5f6c 100644
--- a/chain/block.go
+++ b/chain/types/block.go
@@ -1,4 +1,4 @@
-package chain
+package types
import (
"bytes"
@@ -153,7 +153,7 @@ func (block *Block) State() *state.State {
return block.state
}
-func (block *Block) Transactions() []*Transaction {
+func (block *Block) Transactions() Transactions {
return block.transactions
}
diff --git a/chain/bloom9.go b/chain/types/bloom9.go
index c610bd101..626711cca 100644
--- a/chain/bloom9.go
+++ b/chain/types/bloom9.go
@@ -1,4 +1,4 @@
-package chain
+package types
import (
"math/big"
diff --git a/chain/bloom9_test.go b/chain/types/bloom9_test.go
index 8b1b962cb..74e00cac6 100644
--- a/chain/bloom9_test.go
+++ b/chain/types/bloom9_test.go
@@ -1,7 +1,9 @@
-package chain
+package types
+/*
import (
"testing"
+
"github.com/ethereum/go-ethereum/state"
)
@@ -17,7 +19,7 @@ func TestBloom9(t *testing.T) {
}
}
-/*
+
func TestAddress(t *testing.T) {
block := &Block{}
block.Coinbase = ethutil.Hex2Bytes("22341ae42d6dd7384bc8584e50419ea3ac75b83f")
diff --git a/chain/types/common.go b/chain/types/common.go
new file mode 100644
index 000000000..ae0e7c3fa
--- /dev/null
+++ b/chain/types/common.go
@@ -0,0 +1,10 @@
+package types
+
+import (
+ "math/big"
+ "github.com/ethereum/go-ethereum/state"
+)
+
+type BlockProcessor interface {
+ ProcessWithParent(*Block, *Block) (*big.Int, state.Messages, error)
+}
diff --git a/chain/derive_sha.go b/chain/types/derive_sha.go
index 4246aeb02..1897ff198 100644
--- a/chain/derive_sha.go
+++ b/chain/types/derive_sha.go
@@ -1,4 +1,4 @@
-package chain
+package types
import (
"github.com/ethereum/go-ethereum/ethutil"
diff --git a/chain/receipt.go b/chain/types/receipt.go
index fa53f1cdb..25fa8fb07 100644
--- a/chain/receipt.go
+++ b/chain/types/receipt.go
@@ -1,4 +1,4 @@
-package chain
+package types
import (
"bytes"
@@ -16,6 +16,10 @@ type Receipt struct {
logs state.Logs
}
+func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt {
+ return &Receipt{PostState: ethutil.CopyBytes(root), CumulativeGasUsed: cumalativeGasUsed}
+}
+
func NewRecieptFromValue(val *ethutil.Value) *Receipt {
r := &Receipt{}
r.RlpValueDecode(val)
@@ -23,6 +27,10 @@ func NewRecieptFromValue(val *ethutil.Value) *Receipt {
return r
}
+func (self *Receipt) SetLogs(logs state.Logs) {
+ self.logs = logs
+}
+
func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) {
self.PostState = decoder.Get(0).Bytes()
self.CumulativeGasUsed = decoder.Get(1).BigInt()
diff --git a/chain/transaction.go b/chain/types/transaction.go
index d81a0ea1b..626a7e5ce 100644
--- a/chain/transaction.go
+++ b/chain/types/transaction.go
@@ -1,4 +1,4 @@
-package chain
+package types
import (
"fmt"
diff --git a/chain/types/transaction_test.go b/chain/types/transaction_test.go
new file mode 100644
index 000000000..ab1254f4c
--- /dev/null
+++ b/chain/types/transaction_test.go
@@ -0,0 +1 @@
+package types
diff --git a/chain/vm_env.go b/chain/vm_env.go
index 4f3dc3ca4..c1911ff51 100644
--- a/chain/vm_env.go
+++ b/chain/vm_env.go
@@ -3,17 +3,18 @@ package chain
import (
"math/big"
+ "github.com/ethereum/go-ethereum/chain/types"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
)
type VMEnv struct {
state *state.State
- block *Block
- tx *Transaction
+ block *types.Block
+ tx *types.Transaction
}
-func NewEnv(state *state.State, tx *Transaction, block *Block) *VMEnv {
+func NewEnv(state *state.State, tx *types.Transaction, block *types.Block) *VMEnv {
return &VMEnv{
state: state,
block: block,