From 5ebae82eeb3f5ecdffb96f9d692523d0b0d4f759 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 2 Dec 2014 12:23:27 +0100 Subject: [PATCH 1/6] Additional logging and removed temp merged mining options. --- chain/block_manager.go | 6 +----- chain/chain_manager.go | 2 +- chain/error.go | 4 ++-- cmd/mist/assets/qml/views/miner.qml | 2 ++ 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/chain/block_manager.go b/chain/block_manager.go index c1a28e423..9133475b6 100644 --- a/chain/block_manager.go +++ b/chain/block_manager.go @@ -185,8 +185,7 @@ func (sm *BlockManager) Process(block *Block) (td *big.Int, msgs state.Messages, defer sm.mutex.Unlock() if sm.bc.HasBlock(block.Hash()) { - fmt.Println("already having this block") - return nil, nil, nil + return nil, nil, &KnownBlockError{block.Number, block.Hash()} } if !sm.bc.HasBlock(block.PrevHash) { @@ -233,12 +232,10 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me // Block validation if err = sm.ValidateBlock(block, parent); err != nil { - statelogger.Errorln("validating block:", err) return } if err = sm.AccumelateRewards(state, block, parent); err != nil { - statelogger.Errorln("accumulating reward", err) return } @@ -271,7 +268,6 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me sm.transState = state.Copy() sm.eth.TxPool().RemoveSet(block.Transactions()) - fmt.Println("TD", td) return td, messages, nil } else { diff --git a/chain/chain_manager.go b/chain/chain_manager.go index 3448b02dd..45af61e48 100644 --- a/chain/chain_manager.go +++ b/chain/chain_manager.go @@ -330,10 +330,10 @@ func (self *ChainManager) InsertChain(chain Blocks) error { continue } + chainlogger.Infof("block process failed %v (%x)\n", block.Number, block.Hash()[:4]) return err } - fmt.Println(td, messages, err) self.add(block) self.SetTotalDifficulty(td) self.Ethereum.EventMux().Post(NewBlockEvent{block}) diff --git a/chain/error.go b/chain/error.go index 7dce2b608..0c4d6e59e 100644 --- a/chain/error.go +++ b/chain/error.go @@ -128,12 +128,12 @@ func IsTDError(e error) bool { } type KnownBlockError struct { - number uint64 + number *big.Int hash []byte } func (self *KnownBlockError) Error() string { - return fmt.Sprintf("block %d already known (%x)", self.number, self.hash[0:4]) + return fmt.Sprintf("block %v already known (%x)", self.number, self.hash[0:4]) } func IsKnownBlockErr(e error) bool { _, ok := e.(*KnownBlockError) diff --git a/cmd/mist/assets/qml/views/miner.qml b/cmd/mist/assets/qml/views/miner.qml index 2d59bb3a4..e0182649f 100644 --- a/cmd/mist/assets/qml/views/miner.qml +++ b/cmd/mist/assets/qml/views/miner.qml @@ -119,12 +119,14 @@ Rectangle { } } Component.onCompleted: { + /* // XXX Temp. replace with above eventually var tmpItems = ["JEVCoin", "Some coin", "Other coin", "Etc coin"]; var address = "e6716f9544a56c530d868e4bfbacb172315bdead"; for (var i = 0; i < tmpItems.length; i++) { mergedMiningModel.append({checked: false, name: tmpItems[i], address: address, id: 0, itemId: i}); } + */ } } } From cb4d168ecc9f6c2ecdb1a8f3308f8f3eb9f02376 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 2 Dec 2014 17:22:33 +0100 Subject: [PATCH 2/6] Updated LOG to match proper gas in all cases --- block_pool.go | 26 -------------------------- chain/chain_manager.go | 5 +++-- chain/dagger.go | 14 +++++++++----- peer.go | 2 +- vm/types.go | 8 +------- vm/vm_debug.go | 5 +++-- 6 files changed, 17 insertions(+), 43 deletions(-) diff --git a/block_pool.go b/block_pool.go index 69c7a54de..2cc705514 100644 --- a/block_pool.go +++ b/block_pool.go @@ -336,32 +336,6 @@ out: self.Remove(block.Hash()) } } - - /* - // Test and import - bchain := chain.NewChain(blocks) - _, err := chainManager.TestChain(bchain) - if err != nil && !chain.IsTDError(err) { - poollogger.Debugln(err) - - self.Reset() - - if self.peer != nil && self.peer.conn != nil { - poollogger.Debugf("Punishing peer for supplying bad chain (%v)\n", self.peer.conn.RemoteAddr()) - } - - // This peer gave us bad hashes and made us fetch a bad chain, therefor he shall be punished. - self.eth.BlacklistPeer(self.peer) - self.peer.StopWithReason(DiscBadPeer) - self.td = ethutil.Big0 - self.peer = nil - } else { - chainManager.InsertChain(bchain) - for _, block := range blocks { - self.Remove(block.Hash()) - } - } - */ } } } diff --git a/chain/chain_manager.go b/chain/chain_manager.go index 45af61e48..b71510833 100644 --- a/chain/chain_manager.go +++ b/chain/chain_manager.go @@ -321,7 +321,6 @@ func NewChain(blocks Blocks) *BlockChain { return chain } -// This function assumes you've done your checking. No checking is done at this stage anymore func (self *ChainManager) InsertChain(chain Blocks) error { for _, block := range chain { td, messages, err := self.Ethereum.BlockManager().Process(block) @@ -330,7 +329,9 @@ func (self *ChainManager) InsertChain(chain Blocks) error { continue } - chainlogger.Infof("block process failed %v (%x)\n", block.Number, block.Hash()[:4]) + chainlogger.Infof("block #%v process failed (%x)\n", block.Number, block.Hash()[:4]) + chainlogger.Infoln(block) + chainlogger.Infoln(err) return err } diff --git a/chain/dagger.go b/chain/dagger.go index 2cf70e091..a0ccaeeca 100644 --- a/chain/dagger.go +++ b/chain/dagger.go @@ -81,13 +81,17 @@ func (pow *EasyPow) Verify(hash []byte, diff *big.Int, nonce []byte) bool { d := append(hash, nonce...) sha.Write(d) - v := ethutil.BigPow(2, 256) - ret := new(big.Int).Div(v, diff) + verification := new(big.Int).Div(ethutil.BigPow(2, 256), diff) + res := ethutil.U256(ethutil.BigD(sha.Sum(nil))) - res := new(big.Int) - res.SetBytes(sha.Sum(nil)) + /* + fmt.Printf("hash w/o nonce %x\n", hash) + fmt.Printf("2**256 / %v = %v\n", diff, verification) + fmt.Printf("%v <= %v\n", res, verification) + fmt.Printf("vlen: %d rlen: %d\n", len(verification.Bytes()), len(res.Bytes())) + */ - return res.Cmp(ret) == -1 + return res.Cmp(verification) <= 0 } func (pow *EasyPow) SetHash(hash *big.Int) { diff --git a/peer.go b/peer.go index 1b5f47f11..5e3f368d0 100644 --- a/peer.go +++ b/peer.go @@ -24,7 +24,7 @@ const ( // The size of the output buffer for writing messages outputBufferSize = 50 // Current protocol version - ProtocolVersion = 45 + ProtocolVersion = 46 // Current P2P version P2PVersion = 2 // Ethereum network version diff --git a/vm/types.go b/vm/types.go index 0b20fb655..530dbf400 100644 --- a/vm/types.go +++ b/vm/types.go @@ -163,8 +163,8 @@ const ( // 0xf0 range - closures CREATE OpCode = 0xf0 + iota CALL - RETURN CALLCODE + RETURN // 0x70 range - other SUICIDE = 0xff @@ -309,12 +309,6 @@ var opCodeToString = map[OpCode]string{ SWAP15: "SWAP15", SWAP16: "SWAP16", - LOG0: "LOG0", - LOG1: "LOG1", - LOG2: "LOG2", - LOG3: "LOG3", - LOG4: "LOG4", - // 0xf0 range CREATE: "CREATE", CALL: "CALL", diff --git a/vm/vm_debug.go b/vm/vm_debug.go index ea94987d1..dbab8fbcb 100644 --- a/vm/vm_debug.go +++ b/vm/vm_debug.go @@ -165,10 +165,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { n := int(op - LOG0) require(n + 2) - mSize, mStart := stack.Peekn() gas.Set(GasLog) addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog)) - addStepGasUsage(new(big.Int).Add(mSize, mStart)) + + mSize, _ := stack.Peekn() + addStepGasUsage(mSize) case EXP: require(2) From 0a22dc2ce5d0e69004272f44af972e387144c126 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 2 Dec 2014 22:22:43 +0100 Subject: [PATCH 3/6] Check coinbase for from/to inclusion --- chain/block_manager.go | 17 +++++++++++------ chain/filter.go | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/chain/block_manager.go b/chain/block_manager.go index 9133475b6..fe84a94ca 100644 --- a/chain/block_manager.go +++ b/chain/block_manager.go @@ -275,16 +275,24 @@ 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) { - coinbase := state.GetOrNewStateObject(block.Coinbase) +func (sm *BlockManager) ApplyDiff(statedb *state.State, parent, block *Block) (receipts Receipts, err error) { + coinbase := statedb.GetOrNewStateObject(block.Coinbase) coinbase.SetGasPool(block.CalcGasLimit(parent)) // Process the transactions on to current block - receipts, _, _, _, err = sm.ProcessTransactions(coinbase, state, block, parent, block.Transactions()) + receipts, _, _, _, err = sm.ProcessTransactions(coinbase, statedb, block, parent, block.Transactions()) if err != nil { return nil, err } + statedb.Manifest().AddMessage(&state.Message{ + To: block.Coinbase, From: block.Coinbase, + Input: nil, + Origin: nil, + Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number, + Value: new(big.Int), + }) + return receipts, nil } @@ -303,9 +311,6 @@ func (sm *BlockManager) CalculateTD(block *Block) (*big.Int, bool) { // is greater than the previous. if td.Cmp(sm.bc.TD) > 0 { return td, true - - // Set the new total difficulty back to the block chain - //sm.bc.SetTotalDifficulty(td) } return nil, false diff --git a/chain/filter.go b/chain/filter.go index 3c0b02d4f..5b7543167 100644 --- a/chain/filter.go +++ b/chain/filter.go @@ -175,7 +175,7 @@ func (self *Filter) bloomFilter(block *Block) bool { var fromIncluded, toIncluded bool if len(self.from) > 0 { for _, from := range self.from { - if BloomLookup(block.LogsBloom, from) { + if BloomLookup(block.LogsBloom, from) || bytes.Equal(block.Coinbase, from) { fromIncluded = true break } @@ -186,7 +186,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 BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) || bytes.Equal(block.Coinbase, to) { toIncluded = true break } From edc52bdcbf65b396a838a347b370ea859ae58247 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 2 Dec 2014 22:23:20 +0100 Subject: [PATCH 4/6] Updated value for mined blocks. Closes #197 --- cmd/mist/assets/qml/views/wallet.qml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/mist/assets/qml/views/wallet.qml b/cmd/mist/assets/qml/views/wallet.qml index a57e7869a..9ffb1024d 100644 --- a/cmd/mist/assets/qml/views/wallet.qml +++ b/cmd/mist/assets/qml/views/wallet.qml @@ -16,7 +16,13 @@ Rectangle { anchors.fill: parent function onReady() { - menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address)) + setBalance() + } + + function setBalance() { + balance.text = "Balance: " + eth.numberToHuman(eth.balanceAt(eth.key().address)) + if(menuItem) + menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address)) } ListModel { @@ -39,7 +45,6 @@ Rectangle { Text { id: balance - text: "Balance: " + eth.numberToHuman(eth.balanceAt(eth.key().address)) font.pixelSize: 24 anchors { horizontalCenter: parent.horizontalCenter @@ -126,7 +131,6 @@ Rectangle { var value = txValue.text + denomModel.get(valueDenom.currentIndex).zeros; var gasPrice = "10000000000000" var res = eth.transact({from: eth.key().privateKey, to: txTo.text, value: value, gas: "500", gasPrice: gasPrice}) - console.log(res) } } } @@ -158,6 +162,8 @@ Rectangle { } function addTxs(messages) { + setBalance() + for(var i = 0; i < messages.length; i++) { var message = messages.get(i); var to = eth.lookupName(message.to); From f7789220862f67c2aadaf7b6a44fcd54152dd234 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 2 Dec 2014 22:37:45 +0100 Subject: [PATCH 5/6] Set proper message value --- chain/block.go | 2 ++ chain/block_manager.go | 56 ++++++++++++++++++++------------------- chain/state_transition.go | 6 ----- cmd/utils/cmd.go | 2 +- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/chain/block.go b/chain/block.go index dccb7ca41..6b976cc14 100644 --- a/chain/block.go +++ b/chain/block.go @@ -97,6 +97,8 @@ type Block struct { receipts Receipts TxSha, ReceiptSha []byte LogsBloom []byte + + Reward *big.Int } func NewBlockFromBytes(raw []byte) *Block { diff --git a/chain/block_manager.go b/chain/block_manager.go index fe84a94ca..d89789255 100644 --- a/chain/block_manager.go +++ b/chain/block_manager.go @@ -117,6 +117,19 @@ func (sm *BlockManager) ChainManager() *ChainManager { return sm.bc } +func (sm *BlockManager) TransitionState(statedb *state.State, parent, block *Block) (receipts Receipts, err error) { + coinbase := statedb.GetOrNewStateObject(block.Coinbase) + coinbase.SetGasPool(block.CalcGasLimit(parent)) + + // Process the transactions on to current block + receipts, _, _, _, err = sm.ProcessTransactions(coinbase, statedb, block, parent, block.Transactions()) + if err != nil { + return nil, err + } + + return receipts, nil +} + func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state *state.State, block, parent *Block, txs Transactions) (Receipts, Transactions, Transactions, Transactions, error) { var ( receipts Receipts @@ -124,6 +137,7 @@ func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state erroneous Transactions totalUsedGas = big.NewInt(0) err error + cumulativeSum = new(big.Int) ) done: @@ -155,6 +169,7 @@ done: } txGas.Sub(txGas, st.gas) + cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice)) // Update the state with pending changes state.Update(txGas) @@ -174,6 +189,7 @@ done: } } + block.Reward = cumulativeSum block.GasUsed = totalUsedGas return receipts, handled, unhandled, erroneous, err @@ -211,7 +227,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me fmt.Printf("## %x %x ##\n", block.Hash(), block.Number) } - _, err = sm.ApplyDiff(state, parent, block) + _, err = sm.TransitionState(state, parent, block) if err != nil { return } @@ -275,27 +291,6 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me } } -func (sm *BlockManager) ApplyDiff(statedb *state.State, parent, block *Block) (receipts Receipts, err error) { - coinbase := statedb.GetOrNewStateObject(block.Coinbase) - coinbase.SetGasPool(block.CalcGasLimit(parent)) - - // Process the transactions on to current block - receipts, _, _, _, err = sm.ProcessTransactions(coinbase, statedb, block, parent, block.Transactions()) - if err != nil { - return nil, err - } - - statedb.Manifest().AddMessage(&state.Message{ - To: block.Coinbase, From: block.Coinbase, - Input: nil, - Origin: nil, - Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number, - Value: new(big.Int), - }) - - return receipts, nil -} - func (sm *BlockManager) CalculateTD(block *Block) (*big.Int, bool) { uncleDiff := new(big.Int) for _, uncle := range block.Uncles { @@ -345,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(statedb *state.State, block, parent *Block) error { reward := new(big.Int).Set(BlockReward) knownUncles := ethutil.Set(parent.Uncles) @@ -374,17 +369,25 @@ func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *Blo r := new(big.Int) r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16)) - uncleAccount := state.GetAccount(uncle.Coinbase) + uncleAccount := statedb.GetAccount(uncle.Coinbase) uncleAccount.AddAmount(r) reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) } // Get the account associated with the coinbase - account := state.GetAccount(block.Coinbase) + account := statedb.GetAccount(block.Coinbase) // Reward amount of ether to the coinbase address account.AddAmount(reward) + statedb.Manifest().AddMessage(&state.Message{ + To: block.Coinbase, From: block.Coinbase, + Input: nil, + Origin: nil, + Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number, + Value: new(big.Int).Add(reward, block.Reward), + }) + return nil } @@ -402,8 +405,7 @@ func (sm *BlockManager) GetMessages(block *Block) (messages []*state.Message, er defer state.Reset() - sm.ApplyDiff(state, parent, block) - + sm.TransitionState(state, parent, block) sm.AccumelateRewards(state, block, parent) return state.Manifest().Messages, nil diff --git a/chain/state_transition.go b/chain/state_transition.go index f9b82c58b..53c306903 100644 --- a/chain/state_transition.go +++ b/chain/state_transition.go @@ -168,12 +168,6 @@ func (self *StateTransition) TransitionState() (err error) { return } - //dataPrice := big.NewInt(int64(len(self.data))) - //dataPrice.Mul(dataPrice, vm.GasData) - //if err = self.UseGas(dataPrice); err != nil { - // return - //} - if sender.Balance().Cmp(self.value) < 0 { return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance) } diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 96590b20f..d9b26c701 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -317,7 +317,7 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error { parent := ethereum.ChainManager().GetBlock(block.PrevHash) - _, err := ethereum.BlockManager().ApplyDiff(parent.State(), parent, block) + _, err := ethereum.BlockManager().TransitionState(parent.State(), parent, block) if err != nil { return err } From 3d9a4e7084c33cb28a2265c0dd232a0ea3871c92 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 3 Dec 2014 12:21:12 +0100 Subject: [PATCH 6/6] Fixed mem error in vm. Fixed logs tests --- chain/bloom9.go | 4 ++-- cmd/ethereum/main.go | 2 +- cmd/mist/main.go | 2 +- tests/helper/vm.go | 17 +++++++++++------ tests/vm/gh_test.go | 40 ++++++++++++++++++++++++++++++++-------- vm/stack.go | 3 +-- vm/types.go | 5 +++++ vm/vm_debug.go | 10 ++++++---- 8 files changed, 59 insertions(+), 24 deletions(-) diff --git a/chain/bloom9.go b/chain/bloom9.go index c610bd101..9b2e379c8 100644 --- a/chain/bloom9.go +++ b/chain/bloom9.go @@ -11,13 +11,13 @@ import ( func CreateBloom(receipts Receipts) []byte { bin := new(big.Int) for _, receipt := range receipts { - bin.Or(bin, logsBloom(receipt.logs)) + bin.Or(bin, LogsBloom(receipt.logs)) } return ethutil.LeftPadBytes(bin.Bytes(), 64) } -func logsBloom(logs state.Logs) *big.Int { +func LogsBloom(logs state.Logs) *big.Int { bin := new(big.Int) for _, log := range logs { data := [][]byte{log.Address} diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go index 1493de384..60052314c 100644 --- a/cmd/ethereum/main.go +++ b/cmd/ethereum/main.go @@ -30,7 +30,7 @@ import ( const ( ClientIdentifier = "Ethereum(G)" - Version = "0.7.6" + Version = "0.7.7" ) var clilogger = logger.NewLogger("CLI") diff --git a/cmd/mist/main.go b/cmd/mist/main.go index 39beeafdb..8c46de6d9 100644 --- a/cmd/mist/main.go +++ b/cmd/mist/main.go @@ -31,7 +31,7 @@ import ( const ( ClientIdentifier = "Mist" - Version = "0.7.6" + Version = "0.7.7" ) var ethereum *eth.Ethereum diff --git a/tests/helper/vm.go b/tests/helper/vm.go index b4ad93193..8e6645fc3 100644 --- a/tests/helper/vm.go +++ b/tests/helper/vm.go @@ -20,6 +20,8 @@ type Env struct { time int64 difficulty *big.Int gasLimit *big.Int + + logs state.Logs } func NewEnv(state *state.State) *Env { @@ -51,24 +53,27 @@ func (self *Env) Difficulty() *big.Int { return self.difficulty } func (self *Env) BlockHash() []byte { return nil } func (self *Env) State() *state.State { return self.state } func (self *Env) GasLimit() *big.Int { return self.gasLimit } -func (self *Env) AddLog(*state.Log) {} +func (self *Env) AddLog(log *state.Log) { + self.logs = append(self.logs, log) +} func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error { return vm.Transfer(from, to, amount) } -func RunVm(state *state.State, env, exec map[string]string) ([]byte, *big.Int, error) { +func RunVm(state *state.State, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { address := FromHex(exec["address"]) caller := state.GetOrNewStateObject(FromHex(exec["caller"])) - evm := vm.New(NewEnvFromMap(state, env, exec), vm.DebugVmTy) + vmenv := NewEnvFromMap(state, env, exec) + evm := vm.New(vmenv, vm.DebugVmTy) execution := vm.NewExecution(evm, address, FromHex(exec["data"]), ethutil.Big(exec["gas"]), ethutil.Big(exec["gasPrice"]), ethutil.Big(exec["value"])) execution.SkipTransfer = true ret, err := execution.Exec(address, caller) - return ret, execution.Gas, err + return ret, vmenv.logs, execution.Gas, err } -func RunState(state *state.State, env, tx map[string]string) ([]byte, *big.Int, error) { +func RunState(state *state.State, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { address := FromHex(tx["to"]) keyPair, _ := crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(tx["secretKey"]))) caller := state.GetOrNewStateObject(keyPair.Address()) @@ -79,5 +84,5 @@ func RunState(state *state.State, env, tx map[string]string) ([]byte, *big.Int, execution := vm.NewExecution(evm, address, FromHex(tx["data"]), ethutil.Big(tx["gasLimit"]), ethutil.Big(tx["gasPrice"]), ethutil.Big(tx["value"])) ret, err := execution.Exec(address, caller) - return ret, execution.Gas, err + return ret, vmenv.logs, execution.Gas, err } diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go index 5391e0500..523ff46ac 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -6,6 +6,7 @@ import ( "strconv" "testing" + "github.com/ethereum/go-ethereum/chain" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/tests/helper" @@ -18,6 +19,12 @@ type Account struct { Storage map[string]string } +type Log struct { + Address string + Data string + Topics []string +} + func StateObjectFromAccount(addr string, account Account) *state.StateObject { obj := state.NewStateObject(ethutil.Hex2Bytes(addr)) obj.SetBalance(ethutil.Big(account.Balance)) @@ -46,6 +53,7 @@ type VmTest struct { Env Env Exec map[string]string Transaction map[string]string + Logs map[string]Log Gas string Out string Post map[string]Account @@ -57,10 +65,10 @@ func RunVmTest(p string, t *testing.T) { helper.CreateFileTests(t, p, &tests) for name, test := range tests { - state := state.New(helper.NewTrie()) + statedb := state.New(helper.NewTrie()) for addr, account := range test.Pre { obj := StateObjectFromAccount(addr, account) - state.SetStateObject(obj) + statedb.SetStateObject(obj) } // XXX Yeah, yeah... @@ -77,15 +85,16 @@ func RunVmTest(p string, t *testing.T) { } var ( - ret []byte - gas *big.Int - err error + ret []byte + gas *big.Int + err error + logs state.Logs ) if len(test.Exec) > 0 { - ret, gas, err = helper.RunVm(state, env, test.Exec) + ret, logs, gas, err = helper.RunVm(statedb, env, test.Exec) } else { - ret, gas, err = helper.RunState(state, env, test.Transaction) + ret, logs, gas, err = helper.RunState(statedb, env, test.Transaction) } // When an error is returned it doesn't always mean the tests fails. @@ -107,7 +116,7 @@ func RunVmTest(p string, t *testing.T) { } for addr, account := range test.Post { - obj := state.GetStateObject(helper.FromHex(addr)) + obj := statedb.GetStateObject(helper.FromHex(addr)) for addr, value := range account.Storage { v := obj.GetState(helper.FromHex(addr)).Bytes() vexp := helper.FromHex(value) @@ -117,6 +126,16 @@ func RunVmTest(p string, t *testing.T) { } } } + + if len(test.Logs) > 0 { + genBloom := ethutil.LeftPadBytes(chain.LogsBloom(logs).Bytes(), 64) + // Logs within the test itself aren't correct, missing empty fields (32 0s) + for bloom /*logs*/, _ := range test.Logs { + if !bytes.Equal(genBloom, ethutil.Hex2Bytes(bloom)) { + t.Errorf("bloom mismatch") + } + } + } } } @@ -161,6 +180,11 @@ func TestVm(t *testing.T) { RunVmTest(fn, t) } +func TestVmLog(t *testing.T) { + const fn = "../files/vmtests/vmLogTest.json" + RunVmTest(fn, t) +} + func TestStateSystemOperations(t *testing.T) { const fn = "../files/StateTests/stSystemOperationsTest.json" RunVmTest(fn, t) diff --git a/vm/stack.go b/vm/stack.go index 2eca60ad1..98795cc03 100644 --- a/vm/stack.go +++ b/vm/stack.go @@ -147,9 +147,8 @@ func (m *Memory) Get(offset, size int64) []byte { func (self *Memory) Geti(offset, size int64) (cpy []byte) { if len(self.store) > int(offset) { - s := int64(math.Min(float64(len(self.store)), float64(offset+size))) cpy = make([]byte, size) - copy(cpy, self.store[offset:offset+s]) + copy(cpy, self.store[offset:offset+size]) return } diff --git a/vm/types.go b/vm/types.go index 530dbf400..ec9c7e74e 100644 --- a/vm/types.go +++ b/vm/types.go @@ -308,6 +308,11 @@ var opCodeToString = map[OpCode]string{ SWAP14: "SWAP14", SWAP15: "SWAP15", SWAP16: "SWAP16", + LOG0: "LOG0", + LOG1: "LOG1", + LOG2: "LOG2", + LOG3: "LOG3", + LOG4: "LOG4", // 0xf0 range CREATE: "CREATE", diff --git a/vm/vm_debug.go b/vm/vm_debug.go index dbab8fbcb..91d3c55c1 100644 --- a/vm/vm_debug.go +++ b/vm/vm_debug.go @@ -35,7 +35,7 @@ func NewDebugVm(env Environment) *DebugVm { lt = LogTyDiff } - return &DebugVm{env: env, logTy: lt, Recoverable: true} + return &DebugVm{env: env, logTy: lt, Recoverable: false} } func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { @@ -168,8 +168,10 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { gas.Set(GasLog) addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog)) - mSize, _ := stack.Peekn() + mSize, mStart := stack.Peekn() addStepGasUsage(mSize) + + newMemSize = calcMemSize(mStart, mSize) case EXP: require(2) @@ -755,10 +757,10 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { case LOG0, LOG1, LOG2, LOG3, LOG4: n := int(op - LOG0) topics := make([][]byte, n) - mStart, mSize := stack.Pop().Int64(), stack.Pop().Int64() + mSize, mStart := stack.Pop().Int64(), stack.Pop().Int64() data := mem.Geti(mStart, mSize) for i := 0; i < n; i++ { - topics[i] = stack.Pop().Bytes() + topics[i] = ethutil.LeftPadBytes(stack.Pop().Bytes(), 32) } log := &state.Log{closure.Address(), topics, data}