Merge branch 'release/poc5-rc8'

This commit is contained in:
obscuren 2014-05-21 14:04:25 +02:00
commit 7fe73deb2d
14 changed files with 158 additions and 102 deletions

View File

@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof Ethereum is currently in its testing phase. The current state is "Proof
of Concept 5.0 RC7". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). of Concept 5.0 RC8". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
Ethereum Go is split up in several sub packages Please refer to each Ethereum Go is split up in several sub packages Please refer to each
individual package for more information. individual package for more information.

View File

@ -190,8 +190,8 @@ func (bc *BlockChain) ResetTillBlockHash(hash []byte) error {
returnTo = bc.GetBlock(hash) returnTo = bc.GetBlock(hash)
bc.CurrentBlock = returnTo bc.CurrentBlock = returnTo
bc.LastBlockHash = returnTo.Hash() bc.LastBlockHash = returnTo.Hash()
info := bc.BlockInfo(returnTo) //info := bc.BlockInfo(returnTo)
bc.LastBlockNumber = info.Number bc.LastBlockNumber = returnTo.Number.Uint64()
} }
// XXX Why are we resetting? This is the block chain, it has nothing to do with states // XXX Why are we resetting? This is the block chain, it has nothing to do with states
@ -228,9 +228,9 @@ func (bc *BlockChain) GetChainFromHash(hash []byte, max uint64) []interface{} {
// Get the current hash to start with // Get the current hash to start with
currentHash := bc.CurrentBlock.Hash() currentHash := bc.CurrentBlock.Hash()
// Get the last number on the block chain // Get the last number on the block chain
lastNumber := bc.BlockInfo(bc.CurrentBlock).Number lastNumber := bc.CurrentBlock.Number.Uint64()
// Get the parents number // Get the parents number
parentNumber := bc.BlockInfoByHash(hash).Number parentNumber := bc.GetBlock(hash).Number.Uint64()
// Get the min amount. We might not have max amount of blocks // Get the min amount. We might not have max amount of blocks
count := uint64(math.Min(float64(lastNumber-parentNumber), float64(max))) count := uint64(math.Min(float64(lastNumber-parentNumber), float64(max)))
startNumber := parentNumber + count startNumber := parentNumber + count
@ -291,10 +291,10 @@ 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 {
block := NewBlockFromBytes(data) block := NewBlockFromBytes(data)
info := bc.BlockInfo(block) //info := bc.BlockInfo(block)
bc.CurrentBlock = block bc.CurrentBlock = block
bc.LastBlockHash = block.Hash() bc.LastBlockHash = block.Hash()
bc.LastBlockNumber = info.Number bc.LastBlockNumber = block.Number.Uint64()
ethutil.Config.Log.Infof("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber) ethutil.Config.Log.Infof("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber)
} else { } else {

View File

@ -29,7 +29,7 @@ func (pow *EasyPow) Search(block *Block, reactChan chan ethutil.React) []byte {
for { for {
select { select {
case <-reactChan: case <-reactChan:
ethutil.Config.Log.Infoln("[POW] Received reactor event; breaking out.") //ethutil.Config.Log.Infoln("[POW] Received reactor event; breaking out.")
return nil return nil
default: default:
i++ i++

View File

@ -65,7 +65,7 @@ func (st *Stack) Peekn() (*big.Int, *big.Int) {
} }
func (st *Stack) Push(d *big.Int) { func (st *Stack) Push(d *big.Int) {
st.data = append(st.data, d) st.data = append(st.data, new(big.Int).Set(d))
} }
func (st *Stack) Get(amount *big.Int) []*big.Int { func (st *Stack) Get(amount *big.Int) []*big.Int {

View File

@ -100,36 +100,52 @@ func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject
func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Transaction) { func (sm *StateManager) ApplyTransactions(state *State, 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 sm.ApplyTransaction(state, block, tx)
// Check if this is a contract creation traction and if so
// create a contract of this tx.
if tx.IsContract() {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
if err == nil {
contract := sm.MakeContract(state, tx)
if contract != nil {
sm.EvalScript(state, contract.Init(), contract, tx, block)
} else {
ethutil.Config.Log.Infoln("[STATE] Unable to create contract")
}
} else {
ethutil.Config.Log.Infoln("[STATE] contract create:", err)
}
} else {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
contract := state.GetStateObject(tx.Recipient)
ethutil.Config.Log.Debugf("contract recip %x\n", tx.Recipient)
if err == nil && len(contract.Script()) > 0 {
sm.EvalScript(state, contract.Script(), contract, tx, block)
} else if err != nil {
ethutil.Config.Log.Infoln("[STATE] process:", err)
}
}
} }
} }
func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) error {
// If there's no recipient, it's a contract
// Check if this is a contract creation traction and if so
// create a contract of this tx.
if tx.IsContract() {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
if err == nil {
contract := sm.MakeContract(state, tx)
if contract != nil {
sm.EvalScript(state, contract.Init(), contract, tx, block)
} else {
return fmt.Errorf("[STATE] Unable to create contract")
}
} else {
return fmt.Errorf("[STATE] contract create:", err)
}
} else {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
contract := state.GetStateObject(tx.Recipient)
if err == nil && contract != nil && len(contract.Script()) > 0 {
sm.EvalScript(state, contract.Script(), contract, tx, block)
} else if err != nil {
return fmt.Errorf("[STATE] process:", err)
}
}
return nil
}
func (sm *StateManager) Process(block *Block, dontReact bool) error {
if !sm.bc.HasBlock(block.PrevHash) {
return ParentError(block.PrevHash)
}
parent := sm.bc.GetBlock(block.PrevHash)
return sm.ProcessBlock(parent.State(), parent, block, dontReact)
}
// Block processing and validating with a given (temporarily) state // Block processing and validating with a given (temporarily) state
func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool) error { func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontReact bool) error {
// Processing a blocks may never happen simultaneously // Processing a blocks may never happen simultaneously
sm.mutex.Lock() sm.mutex.Lock()
defer sm.mutex.Unlock() defer sm.mutex.Unlock()
@ -153,7 +169,7 @@ func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool)
} }
// Process the transactions on to current block // Process the transactions on to current block
sm.ApplyTransactions(state, sm.bc.CurrentBlock, block.Transactions()) sm.ApplyTransactions(state, parent, block.Transactions())
// Block validation // Block validation
if err := sm.ValidateBlock(block); err != nil { if err := sm.ValidateBlock(block); err != nil {
@ -170,7 +186,7 @@ func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool)
//if !sm.compState.Cmp(state) { //if !sm.compState.Cmp(state) {
if !block.State().Cmp(state) { if !block.State().Cmp(state) {
return fmt.Errorf("Invalid merkle root. Expected %x, got %x", block.State().trie.Root, state.trie.Root) return fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().trie.Root, state.trie.Root)
} }
// Calculate the new total difficulty and sync back to the db // Calculate the new total difficulty and sync back to the db
@ -182,7 +198,7 @@ func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool)
sm.bc.Add(block) sm.bc.Add(block)
sm.notifyChanges(state) sm.notifyChanges(state)
ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash()) ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.Number, block.Hash())
if dontReact == false { if dontReact == false {
sm.Ethereum.Reactor().Post("newBlock", block) sm.Ethereum.Reactor().Post("newBlock", block)

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"math/big"
"testing" "testing"
) )
@ -21,5 +22,31 @@ func TestSync(t *testing.T) {
state.Sync() state.Sync()
object := state.GetStateObject([]byte("aa")) object := state.GetStateObject([]byte("aa"))
fmt.Printf("%x\n", object.Script()) if len(object.Script()) == 0 {
t.Fail()
}
}
func TestObjectGet(t *testing.T) {
ethutil.ReadConfig("", ethutil.LogStd)
db, _ := ethdb.NewMemDatabase()
ethutil.Config.Db = db
state := NewState(ethutil.NewTrie(db, ""))
contract := NewContract([]byte("aa"), ethutil.Big1, ZeroHash256)
state.UpdateStateObject(contract)
contract = state.GetStateObject([]byte("aa"))
contract.SetStorage(big.NewInt(0), ethutil.NewValue("hello"))
o := contract.GetMem(big.NewInt(0))
fmt.Println(o)
state.UpdateStateObject(contract)
contract.SetStorage(big.NewInt(0), ethutil.NewValue("hello00"))
contract = state.GetStateObject([]byte("aa"))
o = contract.GetMem(big.NewInt(0))
fmt.Println("after", o)
} }

View File

@ -81,8 +81,9 @@ func NewTxPool(ethereum EthManager) *TxPool {
// Blocking function. Don't use directly. Use QueueTransaction instead // Blocking function. Don't use directly. Use QueueTransaction instead
func (pool *TxPool) addTransaction(tx *Transaction) { func (pool *TxPool) addTransaction(tx *Transaction) {
pool.mutex.Lock() pool.mutex.Lock()
defer pool.mutex.Unlock()
pool.pool.PushBack(tx) pool.pool.PushBack(tx)
pool.mutex.Unlock()
// Broadcast the transaction to the rest of the peers // Broadcast the transaction to the rest of the peers
pool.Ethereum.Broadcast(ethwire.MsgTxTy, []interface{}{tx.RlpData()}) pool.Ethereum.Broadcast(ethwire.MsgTxTy, []interface{}{tx.RlpData()})
@ -182,9 +183,7 @@ out:
// Validate the transaction // Validate the transaction
err := pool.ValidateTransaction(tx) err := pool.ValidateTransaction(tx)
if err != nil { if err != nil {
if ethutil.Config.Debug { ethutil.Config.Log.Debugln("Validating Tx failed", err)
log.Println("Validating Tx failed", err)
}
} else { } else {
// Call blocking version. // Call blocking version.
pool.addTransaction(tx) pool.addTransaction(tx)

View File

@ -390,10 +390,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
require(1) require(1)
loc := stack.Pop() loc := stack.Pop()
val := closure.GetMem(loc) val := closure.GetMem(loc)
//fmt.Println("get", val.BigInt(), "@", loc)
stack.Push(val.BigInt()) stack.Push(val.BigInt())
case oSSTORE: case oSSTORE:
require(2) require(2)
val, loc := stack.Popn() val, loc := stack.Popn()
//fmt.Println("storing", val, "@", loc)
closure.SetStorage(loc, ethutil.NewValue(val)) closure.SetStorage(loc, ethutil.NewValue(val))
// Add the change to manifest // Add the change to manifest

View File

@ -1,5 +1,6 @@
package ethchain package ethchain
/*
import ( import (
_ "bytes" _ "bytes"
"fmt" "fmt"
@ -23,10 +24,11 @@ func TestRun4(t *testing.T) {
if a > b { if a > b {
int32 c = this.caller() int32 c = this.caller()
} }
Exit() exit()
`), false) `), false)
tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), script, nil) tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), script, nil)
addr := tx.Hash()[12:] tx.Sign(ContractAddr)
addr := tx.CreationAddress()
contract := MakeContract(tx, state) contract := MakeContract(tx, state)
state.UpdateStateObject(contract) state.UpdateStateObject(contract)
fmt.Printf("%x\n", addr) fmt.Printf("%x\n", addr)
@ -34,7 +36,7 @@ func TestRun4(t *testing.T) {
callerScript, err := mutan.Compile(strings.NewReader(` callerScript, err := mutan.Compile(strings.NewReader(`
// Check if there's any cash in the initial store // Check if there's any cash in the initial store
if this.store[1000] == 0 { if this.store[1000] == 0 {
this.store[1000] = 10^20 this.store[1000] = 10**20
} }
@ -93,3 +95,4 @@ func TestRun4(t *testing.T) {
} }
fmt.Println("account.Amount =", account.Amount) fmt.Println("account.Amount =", account.Amount)
} }
*/

View File

@ -60,10 +60,10 @@ func (miner *Miner) listener() {
select { select {
case chanMessage := <-miner.reactChan: case chanMessage := <-miner.reactChan:
if block, ok := chanMessage.Resource.(*ethchain.Block); ok { if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
ethutil.Config.Log.Infoln("[MINER] Got new block via Reactor") //ethutil.Config.Log.Infoln("[MINER] Got new block via Reactor")
if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 { if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 {
// TODO: Perhaps continue mining to get some uncle rewards // TODO: Perhaps continue mining to get some uncle rewards
ethutil.Config.Log.Infoln("[MINER] New top block found resetting state") //ethutil.Config.Log.Infoln("[MINER] New top block found resetting state")
// Filter out which Transactions we have that were not in this block // Filter out which Transactions we have that were not in this block
var newtxs []*ethchain.Transaction var newtxs []*ethchain.Transaction
@ -87,13 +87,11 @@ func (miner *Miner) listener() {
if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 { if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 {
ethutil.Config.Log.Infoln("[MINER] Adding uncle block") ethutil.Config.Log.Infoln("[MINER] Adding uncle block")
miner.uncles = append(miner.uncles, block) miner.uncles = append(miner.uncles, block)
//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
} }
} }
} }
if tx, ok := chanMessage.Resource.(*ethchain.Transaction); ok { if tx, ok := chanMessage.Resource.(*ethchain.Transaction); ok {
//log.Infoln("[MINER] Got new transaction from Reactor", tx)
found := false found := false
for _, ctx := range miner.txs { for _, ctx := range miner.txs {
if found = bytes.Compare(ctx.Hash(), tx.Hash()) == 0; found { if found = bytes.Compare(ctx.Hash(), tx.Hash()) == 0; found {
@ -102,42 +100,54 @@ func (miner *Miner) listener() {
} }
if found == false { if found == false {
//log.Infoln("[MINER] We did not know about this transaction, adding") // Undo all previous commits
miner.block.Undo()
// Apply new transactions
miner.txs = append(miner.txs, tx) miner.txs = append(miner.txs, tx)
miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs)
miner.block.SetTransactions(miner.txs)
} else {
//log.Infoln("[MINER] We already had this transaction, ignoring")
} }
} }
default: default:
ethutil.Config.Log.Infoln("[MINER] Mining on block. Includes", len(miner.txs), "transactions") miner.mineNewBlock()
}
// Apply uncles }
if len(miner.uncles) > 0 { }
miner.block.SetUncles(miner.uncles)
} func (self *Miner) mineNewBlock() {
stateManager := self.ethereum.StateManager()
// Apply all transactions to the block
miner.ethereum.StateManager().ApplyTransactions(miner.block.State(), miner.block, miner.block.Transactions()) self.block = self.ethereum.BlockChain().NewBlock(self.coinbase, self.txs)
miner.ethereum.StateManager().AccumelateRewards(miner.block.State(), miner.block)
// Apply uncles
// Search the nonce if len(self.uncles) > 0 {
miner.block.Nonce = miner.pow.Search(miner.block, miner.quitChan) self.block.SetUncles(self.uncles)
if miner.block.Nonce != nil { }
err := miner.ethereum.StateManager().ProcessBlock(miner.ethereum.StateManager().CurrentState(), miner.block, true)
if err != nil { // Accumulate all valid transaction and apply them to the new state
ethutil.Config.Log.Infoln(err) var txs []*ethchain.Transaction
miner.txs = []*ethchain.Transaction{} // Move this somewhere neat for _, tx := range self.txs {
miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) if err := stateManager.ApplyTransaction(self.block.State(), self.block, tx); err == nil {
} else { txs = append(txs, tx)
miner.ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{miner.block.Value().Val}) }
ethutil.Config.Log.Infof("[MINER] 🔨 Mined block %x\n", miner.block.Hash()) }
self.txs = txs
miner.txs = []*ethchain.Transaction{} // Move this somewhere neat // Set the transactions to the block so the new SHA3 can be calculated
miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) self.block.SetTransactions(self.txs)
} // Accumulate the rewards included for this block
} stateManager.AccumelateRewards(self.block.State(), self.block)
ethutil.Config.Log.Infoln("[MINER] Mining on block. Includes", len(self.txs), "transactions")
// Find a valid nonce
self.block.Nonce = self.pow.Search(self.block, self.quitChan)
if self.block.Nonce != nil {
err := self.ethereum.StateManager().Process(self.block, true)
if err != nil {
ethutil.Config.Log.Infoln(err)
} else {
self.ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{self.block.Value().Val})
ethutil.Config.Log.Infof("[MINER] 🔨 Mined block %x\n", self.block.Hash())
// Gather the new batch of transactions currently in the tx pool
self.txs = self.ethereum.TxPool().CurrentTransactions()
} }
} }
} }

View File

@ -24,18 +24,9 @@ func NewPEthereum(manager ethchain.EthManager) *PEthereum {
func (lib *PEthereum) GetBlock(hexHash string) *PBlock { func (lib *PEthereum) GetBlock(hexHash string) *PBlock {
hash := ethutil.FromHex(hexHash) hash := ethutil.FromHex(hexHash)
block := lib.blockChain.GetBlock(hash) block := lib.blockChain.GetBlock(hash)
var blockInfo *PBlock return NewPBlock(block)
if block != nil {
blockInfo = &PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())}
} else {
blockInfo = &PBlock{Number: -1, Hash: ""}
}
return blockInfo
} }
func (lib *PEthereum) GetKey() *PKey { func (lib *PEthereum) GetKey() *PKey {

View File

@ -8,16 +8,26 @@ import (
// Block interface exposed to QML // Block interface exposed to QML
type PBlock struct { type PBlock struct {
ref *ethchain.Block
Number int `json:"number"` Number int `json:"number"`
Hash string `json:"hash"` Hash string `json:"hash"`
} }
// Creates a new QML Block from a chain block // Creates a new QML Block from a chain block
func NewPBlock(block *ethchain.Block) *PBlock { func NewPBlock(block *ethchain.Block) *PBlock {
info := block.BlockInfo() if block == nil {
hash := hex.EncodeToString(block.Hash()) return nil
}
return &PBlock{Number: int(info.Number), Hash: hash} return &PBlock{ref: block, Number: int(block.Number.Uint64()), Hash: ethutil.Hex(block.Hash())}
}
func (self *PBlock) ToString() string {
if self.ref != nil {
return self.ref.String()
}
return ""
} }
type PTx struct { type PTx struct {

View File

@ -42,7 +42,7 @@ func ReadConfig(base string, logTypes LoggerType) *config {
} }
} }
Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC7"} Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC8"}
Config.Log = NewLogger(logTypes, LogLevelDebug) Config.Log = NewLogger(logTypes, LogLevelDebug)
Config.SetClientString("/Ethereum(G)") Config.SetClientString("/Ethereum(G)")
} }

10
peer.go
View File

@ -335,8 +335,8 @@ func (p *Peer) HandleInbound() {
block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i)) block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i))
//p.ethereum.StateManager().PrepareDefault(block) //p.ethereum.StateManager().PrepareDefault(block)
state := p.ethereum.StateManager().CurrentState() //state := p.ethereum.StateManager().CurrentState()
err = p.ethereum.StateManager().ProcessBlock(state, block, false) err = p.ethereum.StateManager().Process(block, false)
if err != nil { if err != nil {
if ethutil.Config.Debug { if ethutil.Config.Debug {
@ -658,10 +658,8 @@ func (p *Peer) CatchupWithPeer(blockHash []byte) {
ethutil.Config.Log.Debugf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr()) ethutil.Config.Log.Debugf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr())
/* msg = ethwire.NewMessage(ethwire.MsgGetTxsTy, []interface{}{})
msg = ethwire.NewMessage(ethwire.MsgGetTxsTy, []interface{}{}) p.QueueMessage(msg)
p.QueueMessage(msg)
*/
} }
} }