Partially refactored server/txpool/block manager/block chain
The Ethereum structure now complies to a EthManager interface which is being used by the tx pool, block manager and block chain in order to gain access to each other. It's become simpeler. TODO: BlockManager => StateManager
This commit is contained in:
		
							parent
							
								
									5b1613d65b
								
							
						
					
					
						commit
						92f2abdf76
					
				| @ -9,6 +9,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type BlockChain struct { | type BlockChain struct { | ||||||
|  | 	Ethereum EthManager | ||||||
| 	// The famous, the fabulous Mister GENESIIIIIIS (block)
 | 	// The famous, the fabulous Mister GENESIIIIIIS (block)
 | ||||||
| 	genesisBlock *Block | 	genesisBlock *Block | ||||||
| 	// Last known total difficulty
 | 	// Last known total difficulty
 | ||||||
| @ -20,7 +21,7 @@ type BlockChain struct { | |||||||
| 	LastBlockHash []byte | 	LastBlockHash []byte | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewBlockChain() *BlockChain { | func NewBlockChain(ethereum EthManager) *BlockChain { | ||||||
| 	bc := &BlockChain{} | 	bc := &BlockChain{} | ||||||
| 	bc.genesisBlock = NewBlockFromData(ethutil.Encode(Genesis)) | 	bc.genesisBlock = NewBlockFromData(ethutil.Encode(Genesis)) | ||||||
| 
 | 
 | ||||||
| @ -129,6 +130,21 @@ func (bc *BlockChain) GetChain(hash []byte, amount int) []*Block { | |||||||
| 	return blocks | 	return blocks | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func AddTestNetFunds(block *Block) { | ||||||
|  | 	for _, addr := range []string{ | ||||||
|  | 		"8a40bfaa73256b60764c1bf40675a99083efb075", // Gavin
 | ||||||
|  | 		"e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey
 | ||||||
|  | 		"1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit
 | ||||||
|  | 		"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex
 | ||||||
|  | 	} { | ||||||
|  | 		//log.Println("2^200 Wei to", addr)
 | ||||||
|  | 		codedAddr := ethutil.FromHex(addr) | ||||||
|  | 		addr := block.state.GetAccount(codedAddr) | ||||||
|  | 		addr.Amount = ethutil.BigPow(2, 200) | ||||||
|  | 		block.state.UpdateAccount(codedAddr, addr) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (bc *BlockChain) setLastBlock() { | func (bc *BlockChain) setLastBlock() { | ||||||
| 	data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) | 	data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) | ||||||
| 	if len(data) != 0 { | 	if len(data) != 0 { | ||||||
| @ -139,10 +155,21 @@ func (bc *BlockChain) setLastBlock() { | |||||||
| 		bc.LastBlockNumber = info.Number | 		bc.LastBlockNumber = info.Number | ||||||
| 
 | 
 | ||||||
| 		log.Printf("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber) | 		log.Printf("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber) | ||||||
|  | 	} else { | ||||||
|  | 		AddTestNetFunds(bc.genesisBlock) | ||||||
|  | 
 | ||||||
|  | 		bc.genesisBlock.state.trie.Sync() | ||||||
|  | 		// Prepare the genesis block
 | ||||||
|  | 		bc.Add(bc.genesisBlock) | ||||||
|  | 
 | ||||||
|  | 		//log.Printf("root %x\n", bm.bc.genesisBlock.State().Root)
 | ||||||
|  | 		//bm.bc.genesisBlock.PrintHash()
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Set the last know difficulty (might be 0x0 as initial value, Genesis)
 | 	// Set the last know difficulty (might be 0x0 as initial value, Genesis)
 | ||||||
| 	bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) | 	bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) | ||||||
|  | 
 | ||||||
|  | 	log.Printf("Last block: %x\n", bc.CurrentBlock.Hash()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (bc *BlockChain) SetTotalDifficulty(td *big.Int) { | func (bc *BlockChain) SetTotalDifficulty(td *big.Int) { | ||||||
|  | |||||||
| @ -2,11 +2,9 @@ package ethchain | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"encoding/hex" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/ethereum/eth-go/ethutil" | 	"github.com/ethereum/eth-go/ethutil" | ||||||
| 	_ "github.com/ethereum/eth-go/ethwire" | 	"github.com/ethereum/eth-go/ethwire" | ||||||
| 	"log" |  | ||||||
| 	"math/big" | 	"math/big" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| @ -16,14 +14,20 @@ type BlockProcessor interface { | |||||||
| 	ProcessBlock(block *Block) | 	ProcessBlock(block *Block) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type EthManager interface { | ||||||
|  | 	StateManager() *BlockManager | ||||||
|  | 	BlockChain() *BlockChain | ||||||
|  | 	TxPool() *TxPool | ||||||
|  | 	Broadcast(msgType ethwire.MsgType, data []interface{}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // TODO rename to state manager
 | // TODO rename to state manager
 | ||||||
| type BlockManager struct { | type BlockManager struct { | ||||||
| 	// Mutex for locking the block processor. Blocks can only be handled one at a time
 | 	// Mutex for locking the block processor. Blocks can only be handled one at a time
 | ||||||
| 	mutex sync.Mutex | 	mutex sync.Mutex | ||||||
| 
 | 
 | ||||||
| 	// The block chain :)
 | 	// Canonical block chain
 | ||||||
| 	bc *BlockChain | 	bc *BlockChain | ||||||
| 
 |  | ||||||
| 	// States for addresses. You can watch any address
 | 	// States for addresses. You can watch any address
 | ||||||
| 	// at any given time
 | 	// at any given time
 | ||||||
| 	addrStateStore *AddrStateStore | 	addrStateStore *AddrStateStore | ||||||
| @ -33,59 +37,41 @@ type BlockManager struct { | |||||||
| 	// non-persistent key/value memory storage
 | 	// non-persistent key/value memory storage
 | ||||||
| 	mem map[string]*big.Int | 	mem map[string]*big.Int | ||||||
| 
 | 
 | ||||||
| 	TransactionPool *TxPool |  | ||||||
| 
 |  | ||||||
| 	Pow PoW | 	Pow PoW | ||||||
| 
 | 
 | ||||||
| 	Speaker PublicSpeaker | 	Ethereum EthManager | ||||||
| 
 | 
 | ||||||
| 	SecondaryBlockProcessor BlockProcessor | 	SecondaryBlockProcessor BlockProcessor | ||||||
|  | 
 | ||||||
|  | 	// The managed states
 | ||||||
|  | 	// Processor state. Anything processed will be applied to this
 | ||||||
|  | 	// state
 | ||||||
|  | 	procState *State | ||||||
|  | 	// Comparative state it used for comparing and validating end
 | ||||||
|  | 	// results
 | ||||||
|  | 	compState *State | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func AddTestNetFunds(block *Block) { | func NewBlockManager(ethereum EthManager) *BlockManager { | ||||||
| 	for _, addr := range []string{ |  | ||||||
| 		"8a40bfaa73256b60764c1bf40675a99083efb075", // Gavin
 |  | ||||||
| 		"e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey
 |  | ||||||
| 		"1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit
 |  | ||||||
| 		"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex
 |  | ||||||
| 	} { |  | ||||||
| 		//log.Println("2^200 Wei to", addr)
 |  | ||||||
| 		codedAddr, _ := hex.DecodeString(addr) |  | ||||||
| 		addr := block.state.GetAccount(codedAddr) |  | ||||||
| 		addr.Amount = ethutil.BigPow(2, 200) |  | ||||||
| 		block.state.UpdateAccount(codedAddr, addr) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func NewBlockManager(speaker PublicSpeaker) *BlockManager { |  | ||||||
| 	bm := &BlockManager{ | 	bm := &BlockManager{ | ||||||
| 		//server: s,
 |  | ||||||
| 		bc:             NewBlockChain(), |  | ||||||
| 		stack:          NewStack(), | 		stack:          NewStack(), | ||||||
| 		mem:            make(map[string]*big.Int), | 		mem:            make(map[string]*big.Int), | ||||||
| 		Pow:            &EasyPow{}, | 		Pow:            &EasyPow{}, | ||||||
| 		Speaker:        speaker, | 		Ethereum:       ethereum, | ||||||
| 		addrStateStore: NewAddrStateStore(), | 		addrStateStore: NewAddrStateStore(), | ||||||
|  | 		bc:             ethereum.BlockChain(), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if bm.bc.CurrentBlock == nil { |  | ||||||
| 		AddTestNetFunds(bm.bc.genesisBlock) |  | ||||||
| 
 |  | ||||||
| 		bm.bc.genesisBlock.state.trie.Sync() |  | ||||||
| 		// Prepare the genesis block
 |  | ||||||
| 		bm.bc.Add(bm.bc.genesisBlock) |  | ||||||
| 
 |  | ||||||
| 		//log.Printf("root %x\n", bm.bc.genesisBlock.State().Root)
 |  | ||||||
| 		//bm.bc.genesisBlock.PrintHash()
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	log.Printf("Last block: %x\n", bm.bc.CurrentBlock.Hash()) |  | ||||||
| 
 |  | ||||||
| 	return bm | 	return bm | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (bm *BlockManager) ProcState() *State { | ||||||
|  | 	return bm.procState | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Watches any given address and puts it in the address state store
 | // Watches any given address and puts it in the address state store
 | ||||||
| func (bm *BlockManager) WatchAddr(addr []byte) *AccountState { | func (bm *BlockManager) WatchAddr(addr []byte) *AccountState { | ||||||
|  | 	//FIXME account := bm.procState.GetAccount(addr)
 | ||||||
| 	account := bm.bc.CurrentBlock.state.GetAccount(addr) | 	account := bm.bc.CurrentBlock.state.GetAccount(addr) | ||||||
| 
 | 
 | ||||||
| 	return bm.addrStateStore.Add(addr, account) | 	return bm.addrStateStore.Add(addr, account) | ||||||
| @ -105,17 +91,26 @@ func (bm *BlockManager) BlockChain() *BlockChain { | |||||||
| 	return bm.bc | 	return bm.bc | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (bm *BlockManager) MakeContract(tx *Transaction) { | ||||||
|  | 	contract := MakeContract(tx, bm.procState) | ||||||
|  | 	if contract != nil { | ||||||
|  | 		bm.procState.states[string(tx.Hash()[12:])] = contract.state | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (bm *BlockManager) ApplyTransactions(block *Block, txs []*Transaction) { | func (bm *BlockManager) ApplyTransactions(block *Block, txs []*Transaction) { | ||||||
| 	// Process each transaction/contract
 | 	// Process each transaction/contract
 | ||||||
| 	for _, tx := range txs { | 	for _, tx := range txs { | ||||||
| 		// If there's no recipient, it's a contract
 | 		// If there's no recipient, it's a contract
 | ||||||
| 		if tx.IsContract() { | 		if tx.IsContract() { | ||||||
|  | 			//FIXME bm.MakeContract(tx)
 | ||||||
| 			block.MakeContract(tx) | 			block.MakeContract(tx) | ||||||
| 		} else { | 		} else { | ||||||
|  | 			//FIXME if contract := procState.GetContract(tx.Recipient); contract != nil {
 | ||||||
| 			if contract := block.state.GetContract(tx.Recipient); contract != nil { | 			if contract := block.state.GetContract(tx.Recipient); contract != nil { | ||||||
| 				bm.ProcessContract(contract, tx, block) | 				bm.ProcessContract(contract, tx, block) | ||||||
| 			} else { | 			} else { | ||||||
| 				err := bm.TransactionPool.ProcessTransaction(tx, block) | 				err := bm.Ethereum.TxPool().ProcessTransaction(tx, block) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					ethutil.Config.Log.Infoln("[BMGR]", err) | 					ethutil.Config.Log.Infoln("[BMGR]", err) | ||||||
| 				} | 				} | ||||||
| @ -124,6 +119,18 @@ func (bm *BlockManager) ApplyTransactions(block *Block, txs []*Transaction) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // The prepare function, prepares the state manager for the next
 | ||||||
|  | // "ProcessBlock" action.
 | ||||||
|  | func (bm *BlockManager) Prepare(processer *State, comparative *State) { | ||||||
|  | 	bm.compState = comparative | ||||||
|  | 	bm.procState = processer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Default prepare function
 | ||||||
|  | func (bm *BlockManager) PrepareDefault(block *Block) { | ||||||
|  | 	bm.Prepare(bm.BlockChain().CurrentBlock.State(), block.State()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Block processing and validating with a given (temporarily) state
 | // Block processing and validating with a given (temporarily) state
 | ||||||
| func (bm *BlockManager) ProcessBlock(block *Block) error { | func (bm *BlockManager) ProcessBlock(block *Block) error { | ||||||
| 	// Processing a blocks may never happen simultaneously
 | 	// Processing a blocks may never happen simultaneously
 | ||||||
| @ -161,17 +168,20 @@ func (bm *BlockManager) ProcessBlock(block *Block) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// if !bm.compState.Cmp(bm.procState)
 | ||||||
| 	if !block.state.Cmp(bm.bc.CurrentBlock.state) { | 	if !block.state.Cmp(bm.bc.CurrentBlock.state) { | ||||||
| 		return fmt.Errorf("Invalid merkle root. Expected %x, got %x", block.State().trie.Root, bm.bc.CurrentBlock.State().trie.Root) | 		return fmt.Errorf("Invalid merkle root. Expected %x, got %x", block.State().trie.Root, bm.bc.CurrentBlock.State().trie.Root) | ||||||
|  | 		//FIXME return fmt.Errorf("Invalid merkle root. Expected %x, got %x", bm.compState.trie.Root, bm.procState.trie.Root)
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Calculate the new total difficulty and sync back to the db
 | 	// Calculate the new total difficulty and sync back to the db
 | ||||||
| 	if bm.CalculateTD(block) { | 	if bm.CalculateTD(block) { | ||||||
| 		// Sync the current block's state to the database and cancelling out the deferred Undo
 | 		// Sync the current block's state to the database and cancelling out the deferred Undo
 | ||||||
| 		bm.bc.CurrentBlock.Sync() | 		bm.bc.CurrentBlock.Sync() | ||||||
|  | 		//FIXME bm.procState.Sync()
 | ||||||
| 
 | 
 | ||||||
| 		// Broadcast the valid block back to the wire
 | 		// Broadcast the valid block back to the wire
 | ||||||
| 		//bm.Speaker.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})
 | 		//bm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})
 | ||||||
| 
 | 
 | ||||||
| 		// Add the block to the chain
 | 		// Add the block to the chain
 | ||||||
| 		bm.bc.Add(block) | 		bm.bc.Add(block) | ||||||
| @ -207,12 +217,6 @@ func (bm *BlockManager) CalculateTD(block *Block) bool { | |||||||
| 		// Set the new total difficulty back to the block chain
 | 		// Set the new total difficulty back to the block chain
 | ||||||
| 		bm.bc.SetTotalDifficulty(td) | 		bm.bc.SetTotalDifficulty(td) | ||||||
| 
 | 
 | ||||||
| 		/* |  | ||||||
| 			if ethutil.Config.Debug { |  | ||||||
| 				log.Println("[BMGR] TD(block) =", td) |  | ||||||
| 			} |  | ||||||
| 		*/ |  | ||||||
| 
 |  | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -268,16 +272,19 @@ func CalculateUncleReward(block *Block) *big.Int { | |||||||
| func (bm *BlockManager) AccumelateRewards(processor *Block, block *Block) error { | func (bm *BlockManager) AccumelateRewards(processor *Block, block *Block) error { | ||||||
| 	// Get the coinbase rlp data
 | 	// Get the coinbase rlp data
 | ||||||
| 	addr := processor.state.GetAccount(block.Coinbase) | 	addr := processor.state.GetAccount(block.Coinbase) | ||||||
|  | 	//FIXME addr := proc.GetAccount(block.Coinbase)
 | ||||||
| 	// Reward amount of ether to the coinbase address
 | 	// Reward amount of ether to the coinbase address
 | ||||||
| 	addr.AddFee(CalculateBlockReward(block, len(block.Uncles))) | 	addr.AddFee(CalculateBlockReward(block, len(block.Uncles))) | ||||||
| 
 | 
 | ||||||
| 	processor.state.UpdateAccount(block.Coinbase, addr) | 	processor.state.UpdateAccount(block.Coinbase, addr) | ||||||
|  | 	//FIXME proc.UpdateAccount(block.Coinbase, addr)
 | ||||||
| 
 | 
 | ||||||
| 	for _, uncle := range block.Uncles { | 	for _, uncle := range block.Uncles { | ||||||
| 		uncleAddr := processor.state.GetAccount(uncle.Coinbase) | 		uncleAddr := processor.state.GetAccount(uncle.Coinbase) | ||||||
| 		uncleAddr.AddFee(CalculateUncleReward(uncle)) | 		uncleAddr.AddFee(CalculateUncleReward(uncle)) | ||||||
| 
 | 
 | ||||||
| 		processor.state.UpdateAccount(uncle.Coinbase, uncleAddr) | 		processor.state.UpdateAccount(uncle.Coinbase, uncleAddr) | ||||||
|  | 		//FIXME proc.UpdateAccount(uncle.Coinbase, uncleAddr)
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
| @ -298,6 +305,7 @@ func (bm *BlockManager) ProcessContract(contract *Contract, tx *Transaction, blo | |||||||
| 	*/ | 	*/ | ||||||
| 
 | 
 | ||||||
| 	vm := &Vm{} | 	vm := &Vm{} | ||||||
|  | 	//vm.Process(contract, bm.procState, RuntimeVars{
 | ||||||
| 	vm.Process(contract, block.state, RuntimeVars{ | 	vm.Process(contract, block.state, RuntimeVars{ | ||||||
| 		address:     tx.Hash()[12:], | 		address:     tx.Hash()[12:], | ||||||
| 		blockNumber: block.BlockInfo().Number, | 		blockNumber: block.BlockInfo().Number, | ||||||
|  | |||||||
| @ -111,3 +111,41 @@ func (s *State) UpdateAccount(addr []byte, account *Account) { | |||||||
| func (s *State) Cmp(other *State) bool { | func (s *State) Cmp(other *State) bool { | ||||||
| 	return s.trie.Cmp(other.trie) | 	return s.trie.Cmp(other.trie) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type ObjType byte | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	NilTy ObjType = iota | ||||||
|  | 	AccountTy | ||||||
|  | 	ContractTy | ||||||
|  | 
 | ||||||
|  | 	UnknownTy | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Returns the object stored at key and the type stored at key
 | ||||||
|  | // Returns nil if nothing is stored
 | ||||||
|  | func (s *State) Get(key []byte) (*ethutil.Value, ObjType) { | ||||||
|  | 	// Fetch data from the trie
 | ||||||
|  | 	data := s.trie.Get(string(key)) | ||||||
|  | 	// Returns the nil type, indicating nothing could be retrieved.
 | ||||||
|  | 	// Anything using this function should check for this ret val
 | ||||||
|  | 	if data == "" { | ||||||
|  | 		return nil, NilTy | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var typ ObjType | ||||||
|  | 	val := ethutil.NewValueFromBytes([]byte(data)) | ||||||
|  | 	// Check the length of the retrieved value.
 | ||||||
|  | 	// Len 2 = Account
 | ||||||
|  | 	// Len 3 = Contract
 | ||||||
|  | 	// Other = invalid for now. If other types emerge, add them here
 | ||||||
|  | 	if val.Len() == 2 { | ||||||
|  | 		typ = AccountTy | ||||||
|  | 	} else if val.Len() == 3 { | ||||||
|  | 		typ = ContractTy | ||||||
|  | 	} else { | ||||||
|  | 		typ = UnknownTy | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return val, typ | ||||||
|  | } | ||||||
|  | |||||||
| @ -41,10 +41,6 @@ func FindTx(pool *list.List, finder func(*Transaction, *list.Element) bool) *Tra | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type PublicSpeaker interface { |  | ||||||
| 	Broadcast(msgType ethwire.MsgType, data []interface{}) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type TxProcessor interface { | type TxProcessor interface { | ||||||
| 	ProcessTransaction(tx *Transaction) | 	ProcessTransaction(tx *Transaction) | ||||||
| } | } | ||||||
| @ -55,8 +51,7 @@ type TxProcessor interface { | |||||||
| // pool is being drained or synced for whatever reason the transactions
 | // pool is being drained or synced for whatever reason the transactions
 | ||||||
| // will simple queue up and handled when the mutex is freed.
 | // will simple queue up and handled when the mutex is freed.
 | ||||||
| type TxPool struct { | type TxPool struct { | ||||||
| 	//server *Server
 | 	Ethereum EthManager | ||||||
| 	Speaker PublicSpeaker |  | ||||||
| 	// The mutex for accessing the Tx pool.
 | 	// The mutex for accessing the Tx pool.
 | ||||||
| 	mutex sync.Mutex | 	mutex sync.Mutex | ||||||
| 	// Queueing channel for reading and writing incoming
 | 	// Queueing channel for reading and writing incoming
 | ||||||
| @ -67,20 +62,19 @@ type TxPool struct { | |||||||
| 	// The actual pool
 | 	// The actual pool
 | ||||||
| 	pool *list.List | 	pool *list.List | ||||||
| 
 | 
 | ||||||
| 	BlockManager *BlockManager |  | ||||||
| 
 |  | ||||||
| 	SecondaryProcessor TxProcessor | 	SecondaryProcessor TxProcessor | ||||||
| 
 | 
 | ||||||
| 	subscribers []chan TxMsg | 	subscribers []chan TxMsg | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewTxPool() *TxPool { | func NewTxPool(ethereum EthManager) *TxPool { | ||||||
| 	return &TxPool{ | 	return &TxPool{ | ||||||
| 		//server:    s,
 | 		//server:    s,
 | ||||||
| 		mutex:     sync.Mutex{}, | 		mutex:     sync.Mutex{}, | ||||||
| 		pool:      list.New(), | 		pool:      list.New(), | ||||||
| 		queueChan: make(chan *Transaction, txPoolQueueSize), | 		queueChan: make(chan *Transaction, txPoolQueueSize), | ||||||
| 		quit:      make(chan bool), | 		quit:      make(chan bool), | ||||||
|  | 		Ethereum:  ethereum, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -91,7 +85,7 @@ func (pool *TxPool) addTransaction(tx *Transaction) { | |||||||
| 	pool.mutex.Unlock() | 	pool.mutex.Unlock() | ||||||
| 
 | 
 | ||||||
| 	// Broadcast the transaction to the rest of the peers
 | 	// Broadcast the transaction to the rest of the peers
 | ||||||
| 	pool.Speaker.Broadcast(ethwire.MsgTxTy, []interface{}{tx.RlpData()}) | 	pool.Ethereum.Broadcast(ethwire.MsgTxTy, []interface{}{tx.RlpData()}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Process transaction validates the Tx and processes funds from the
 | // Process transaction validates the Tx and processes funds from the
 | ||||||
| @ -152,14 +146,14 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block) (err error | |||||||
| func (pool *TxPool) ValidateTransaction(tx *Transaction) error { | func (pool *TxPool) ValidateTransaction(tx *Transaction) error { | ||||||
| 	// Get the last block so we can retrieve the sender and receiver from
 | 	// Get the last block so we can retrieve the sender and receiver from
 | ||||||
| 	// the merkle trie
 | 	// the merkle trie
 | ||||||
| 	block := pool.BlockManager.BlockChain().CurrentBlock | 	block := pool.Ethereum.BlockChain().CurrentBlock | ||||||
| 	// Something has gone horribly wrong if this happens
 | 	// Something has gone horribly wrong if this happens
 | ||||||
| 	if block == nil { | 	if block == nil { | ||||||
| 		return errors.New("No last block on the block chain") | 		return errors.New("No last block on the block chain") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Get the sender
 | 	// Get the sender
 | ||||||
| 	accountState := pool.BlockManager.GetAddrState(tx.Sender()) | 	accountState := pool.Ethereum.StateManager().GetAddrState(tx.Sender()) | ||||||
| 	sender := accountState.Account | 	sender := accountState.Account | ||||||
| 
 | 
 | ||||||
| 	totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat)) | 	totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat)) | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								ethereum.go
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								ethereum.go
									
									
									
									
									
								
							| @ -37,10 +37,12 @@ type Ethereum struct { | |||||||
| 	//db *ethdb.LDBDatabase
 | 	//db *ethdb.LDBDatabase
 | ||||||
| 	db ethutil.Database | 	db ethutil.Database | ||||||
| 	// Block manager for processing new blocks and managing the block chain
 | 	// Block manager for processing new blocks and managing the block chain
 | ||||||
| 	BlockManager *ethchain.BlockManager | 	blockManager *ethchain.BlockManager | ||||||
| 	// The transaction pool. Transaction can be pushed on this pool
 | 	// The transaction pool. Transaction can be pushed on this pool
 | ||||||
| 	// for later including in the blocks
 | 	// for later including in the blocks
 | ||||||
| 	TxPool *ethchain.TxPool | 	txPool *ethchain.TxPool | ||||||
|  | 	// The canonical chain
 | ||||||
|  | 	blockChain *ethchain.BlockChain | ||||||
| 	// Peers (NYI)
 | 	// Peers (NYI)
 | ||||||
| 	peers *list.List | 	peers *list.List | ||||||
| 	// Nonce
 | 	// Nonce
 | ||||||
| @ -87,19 +89,28 @@ func New(caps Caps, usePnp bool) (*Ethereum, error) { | |||||||
| 		serverCaps:   caps, | 		serverCaps:   caps, | ||||||
| 		nat:          nat, | 		nat:          nat, | ||||||
| 	} | 	} | ||||||
| 	ethereum.TxPool = ethchain.NewTxPool() | 	ethereum.txPool = ethchain.NewTxPool(ethereum) | ||||||
| 	ethereum.TxPool.Speaker = ethereum | 	ethereum.blockChain = ethchain.NewBlockChain(ethereum) | ||||||
| 	ethereum.BlockManager = ethchain.NewBlockManager(ethereum) | 	ethereum.blockManager = ethchain.NewBlockManager(ethereum) | ||||||
| 
 |  | ||||||
| 	ethereum.TxPool.BlockManager = ethereum.BlockManager |  | ||||||
| 	ethereum.BlockManager.TransactionPool = ethereum.TxPool |  | ||||||
| 
 | 
 | ||||||
| 	// Start the tx pool
 | 	// Start the tx pool
 | ||||||
| 	ethereum.TxPool.Start() | 	ethereum.txPool.Start() | ||||||
| 
 | 
 | ||||||
| 	return ethereum, nil | 	return ethereum, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (s *Ethereum) BlockChain() *ethchain.BlockChain { | ||||||
|  | 	return s.blockChain | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *Ethereum) StateManager() *ethchain.BlockManager { | ||||||
|  | 	return s.blockManager | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *Ethereum) TxPool() *ethchain.TxPool { | ||||||
|  | 	return s.txPool | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (s *Ethereum) AddPeer(conn net.Conn) { | func (s *Ethereum) AddPeer(conn net.Conn) { | ||||||
| 	peer := NewPeer(conn, s, true) | 	peer := NewPeer(conn, s, true) | ||||||
| 
 | 
 | ||||||
| @ -253,7 +264,7 @@ func (s *Ethereum) Start() { | |||||||
| 	if ethutil.Config.Seed { | 	if ethutil.Config.Seed { | ||||||
| 		ethutil.Config.Log.Debugln("Seeding") | 		ethutil.Config.Log.Debugln("Seeding") | ||||||
| 		// Testnet seed bootstrapping
 | 		// Testnet seed bootstrapping
 | ||||||
| 		resp, err := http.Get("http://www.ethereum.org/servers.poc3.txt") | 		resp, err := http.Get("https://www.ethereum.org/servers.poc3.txt") | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println("Fetching seed failed:", err) | 			log.Println("Fetching seed failed:", err) | ||||||
| 			return | 			return | ||||||
| @ -292,8 +303,8 @@ func (s *Ethereum) Stop() { | |||||||
| 
 | 
 | ||||||
| 	close(s.quit) | 	close(s.quit) | ||||||
| 
 | 
 | ||||||
| 	s.TxPool.Stop() | 	s.txPool.Stop() | ||||||
| 	s.BlockManager.Stop() | 	s.blockManager.Stop() | ||||||
| 
 | 
 | ||||||
| 	close(s.shutdownChan) | 	close(s.shutdownChan) | ||||||
| } | } | ||||||
|  | |||||||
| @ -224,3 +224,32 @@ func (val *Value) Append(v interface{}) *Value { | |||||||
| 
 | 
 | ||||||
| 	return val | 	return val | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type ValueIterator struct { | ||||||
|  | 	value        *Value | ||||||
|  | 	currentValue *Value | ||||||
|  | 	idx          int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (val *Value) NewIterator() *ValueIterator { | ||||||
|  | 	return &ValueIterator{value: val} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (it *ValueIterator) Next() bool { | ||||||
|  | 	if it.idx >= it.value.Len() { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	it.currentValue = it.value.Get(it.idx) | ||||||
|  | 	it.idx++ | ||||||
|  | 
 | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (it *ValueIterator) Value() *Value { | ||||||
|  | 	return it.currentValue | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (it *ValueIterator) Idx() int { | ||||||
|  | 	return it.idx | ||||||
|  | } | ||||||
|  | |||||||
| @ -50,3 +50,16 @@ func TestValueTypes(t *testing.T) { | |||||||
| 		t.Errorf("expected BigInt to return '%v', got %v", bigExp, bigInt.BigInt()) | 		t.Errorf("expected BigInt to return '%v', got %v", bigExp, bigInt.BigInt()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestIterator(t *testing.T) { | ||||||
|  | 	value := NewValue([]interface{}{1, 2, 3}) | ||||||
|  | 	it := value.NewIterator() | ||||||
|  | 	values := []uint64{1, 2, 3} | ||||||
|  | 	i := 0 | ||||||
|  | 	for it.Next() { | ||||||
|  | 		if values[i] != it.Value().Uint() { | ||||||
|  | 			t.Errorf("Expected %d, got %d", values[i], it.Value().Uint()) | ||||||
|  | 		} | ||||||
|  | 		i++ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								peer.go
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								peer.go
									
									
									
									
									
								
							| @ -18,7 +18,7 @@ const ( | |||||||
| 	// The size of the output buffer for writing messages
 | 	// The size of the output buffer for writing messages
 | ||||||
| 	outputBufferSize = 50 | 	outputBufferSize = 50 | ||||||
| 	// Current protocol version
 | 	// Current protocol version
 | ||||||
| 	ProtocolVersion = 7 | 	ProtocolVersion = 8 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type DiscReason byte | type DiscReason byte | ||||||
| @ -49,7 +49,7 @@ var discReasonToString = []string{ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (d DiscReason) String() string { | func (d DiscReason) String() string { | ||||||
| 	if len(discReasonToString) > int(d) { | 	if len(discReasonToString) < int(d) { | ||||||
| 		return "Unknown" | 		return "Unknown" | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -293,7 +293,8 @@ func (p *Peer) HandleInbound() { | |||||||
| 				var err error | 				var err error | ||||||
| 				for i := msg.Data.Len() - 1; i >= 0; i-- { | 				for i := msg.Data.Len() - 1; i >= 0; i-- { | ||||||
| 					block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i)) | 					block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i)) | ||||||
| 					err = p.ethereum.BlockManager.ProcessBlock(block) | 					// FIXME p.ethereum.BlockManager.DefaultPrepare(block)
 | ||||||
|  | 					err = p.ethereum.StateManager().ProcessBlock(block) | ||||||
| 
 | 
 | ||||||
| 					if err != nil { | 					if err != nil { | ||||||
| 						if ethutil.Config.Debug { | 						if ethutil.Config.Debug { | ||||||
| @ -332,7 +333,7 @@ func (p *Peer) HandleInbound() { | |||||||
| 				// in the TxPool where it will undergo validation and
 | 				// in the TxPool where it will undergo validation and
 | ||||||
| 				// processing when a new block is found
 | 				// processing when a new block is found
 | ||||||
| 				for i := 0; i < msg.Data.Len(); i++ { | 				for i := 0; i < msg.Data.Len(); i++ { | ||||||
| 					p.ethereum.TxPool.QueueTransaction(ethchain.NewTransactionFromData(msg.Data.Get(i).Encode())) | 					p.ethereum.TxPool().QueueTransaction(ethchain.NewTransactionFromData(msg.Data.Get(i).Encode())) | ||||||
| 				} | 				} | ||||||
| 			case ethwire.MsgGetPeersTy: | 			case ethwire.MsgGetPeersTy: | ||||||
| 				// Flag this peer as a 'requested of new peers' this to
 | 				// Flag this peer as a 'requested of new peers' this to
 | ||||||
| @ -374,15 +375,16 @@ func (p *Peer) HandleInbound() { | |||||||
| 				// Check each SHA block hash from the message and determine whether
 | 				// Check each SHA block hash from the message and determine whether
 | ||||||
| 				// the SHA is in the database
 | 				// the SHA is in the database
 | ||||||
| 				for i := 0; i < l; i++ { | 				for i := 0; i < l; i++ { | ||||||
| 					if data := msg.Data.Get(i).Bytes(); p.ethereum.BlockManager.BlockChain().HasBlock(data) { | 					if data := | ||||||
| 						parent = p.ethereum.BlockManager.BlockChain().GetBlock(data) | 						msg.Data.Get(i).Bytes(); p.ethereum.StateManager().BlockChain().HasBlock(data) { | ||||||
|  | 						parent = p.ethereum.BlockChain().GetBlock(data) | ||||||
| 						break | 						break | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// If a parent is found send back a reply
 | 				// If a parent is found send back a reply
 | ||||||
| 				if parent != nil { | 				if parent != nil { | ||||||
| 					chain := p.ethereum.BlockManager.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks) | 					chain := p.ethereum.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks) | ||||||
| 					p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain)) | 					p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain)) | ||||||
| 				} else { | 				} else { | ||||||
| 					// If no blocks are found we send back a reply with msg not in chain
 | 					// If no blocks are found we send back a reply with msg not in chain
 | ||||||
| @ -554,10 +556,10 @@ func (p *Peer) String() string { | |||||||
| func (p *Peer) CatchupWithPeer() { | func (p *Peer) CatchupWithPeer() { | ||||||
| 	if !p.catchingUp { | 	if !p.catchingUp { | ||||||
| 		p.catchingUp = true | 		p.catchingUp = true | ||||||
| 		msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{p.ethereum.BlockManager.BlockChain().CurrentBlock.Hash(), uint64(50)}) | 		msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{p.ethereum.BlockChain().CurrentBlock.Hash(), uint64(50)}) | ||||||
| 		p.QueueMessage(msg) | 		p.QueueMessage(msg) | ||||||
| 
 | 
 | ||||||
| 		ethutil.Config.Log.Debugf("Requesting blockchain %x...\n", p.ethereum.BlockManager.BlockChain().CurrentBlock.Hash()[:4]) | 		ethutil.Config.Log.Debugf("Requesting blockchain %x...\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4]) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user