diff --git a/chain/block_manager.go b/chain/block_manager.go index e40ff7955..56511113d 100644 --- a/chain/block_manager.go +++ b/chain/block_manager.go @@ -118,6 +118,19 @@ func (sm *BlockManager) ChainManager() *ChainManager { return sm.bc } +func (sm *BlockManager) TransitionState(statedb *state.State, parent, block *types.Block) (receipts types.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 *types.Block, txs types.Transactions) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { var ( receipts types.Receipts @@ -125,6 +138,7 @@ func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state erroneous types.Transactions totalUsedGas = big.NewInt(0) err error + cumulativeSum = new(big.Int) ) done: @@ -156,6 +170,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) @@ -176,6 +191,7 @@ done: } } + block.Reward = cumulativeSum block.GasUsed = totalUsedGas return receipts, handled, unhandled, erroneous, err @@ -187,8 +203,7 @@ func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Mes 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) { @@ -214,7 +229,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I 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 } @@ -235,12 +250,10 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I // 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 } @@ -273,7 +286,6 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I sm.transState = state.Copy() sm.eth.TxPool().RemoveSet(block.Transactions()) - fmt.Println("TD", td) return td, messages, nil } else { @@ -281,19 +293,6 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I } } -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)) - - // Process the transactions on to current block - receipts, _, _, _, err = sm.ProcessTransactions(coinbase, state, block, parent, block.Transactions()) - if err != nil { - return nil, err - } - - return receipts, nil -} - func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { uncleDiff := new(big.Int) for _, uncle := range block.Uncles { @@ -309,9 +308,6 @@ func (sm *BlockManager) CalculateTD(block *types.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 @@ -375,17 +371,25 @@ func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *typ 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 } @@ -403,8 +407,7 @@ func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Messa 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/chain_manager.go b/chain/chain_manager.go index 8e0529533..8525ffdfd 100644 --- a/chain/chain_manager.go +++ b/chain/chain_manager.go @@ -258,6 +258,9 @@ func (self *ChainManager) InsertChain(chain Blocks) error { continue } + 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 f7e2229e9..507850389 100644 --- a/chain/dagger.go +++ b/chain/dagger.go @@ -82,13 +82,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/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/chain/filter.go b/chain/filter.go index fd8adaa8f..bb8db38a5 100644 --- a/chain/filter.go +++ b/chain/filter.go @@ -176,7 +176,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { var fromIncluded, toIncluded bool if len(self.from) > 0 { for _, from := range self.from { - if types.BloomLookup(block.LogsBloom, from) { + if types.BloomLookup(block.LogsBloom, from) || bytes.Equal(block.Coinbase, from) { fromIncluded = true break } @@ -187,7 +187,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { if len(self.to) > 0 { for _, to := range self.to { - if types.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()) || bytes.Equal(block.Coinbase, to) { toIncluded = true break } diff --git a/chain/state_transition.go b/chain/state_transition.go index 53b1f6e2d..8f7b55cd4 100644 --- a/chain/state_transition.go +++ b/chain/state_transition.go @@ -169,12 +169,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/chain/types/block.go b/chain/types/block.go index 5c8bb5f6c..feab7072f 100644 --- a/chain/types/block.go +++ b/chain/types/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/types/bloom9.go b/chain/types/bloom9.go index 626711cca..77aa6eef5 100644 --- a/chain/types/bloom9.go +++ b/chain/types/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 c351167f2..7e67a6dcc 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/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}); } + */ } } } 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); 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/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 } diff --git a/peer.go b/peer.go index a0ee9dcc4..ed908265a 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/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 50722bd5b..4c18d29e6 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -141,6 +141,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" @@ -153,6 +154,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)) @@ -181,6 +188,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 @@ -192,10 +200,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... @@ -212,15 +220,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. @@ -242,7 +251,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) @@ -252,6 +261,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") + } + } + } } } @@ -296,6 +315,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/execution.go b/vm/execution.go index f8a772a1d..4df77729e 100644 --- a/vm/execution.go +++ b/vm/execution.go @@ -26,7 +26,7 @@ func (self *Execution) Addr() []byte { func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) ([]byte, error) { // Retrieve the executing code - code := self.vm.Env().State().GetCode(codeAddr) + code := self.vm.Env().GetCode(codeAddr) return self.exec(code, codeAddr, caller) } @@ -34,13 +34,11 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) ([]byte, error) func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte, err error) { env := self.vm.Env() - vmlogger.Debugf("pre state %x\n", env.State().Root()) snapshot := env.State().Copy() defer func() { if IsDepthErr(err) || IsOOGErr(err) { env.State().Set(snapshot) } - vmlogger.Debugf("post state %x\n", env.State().Root()) }() msg := env.State().Manifest().AddMessage(&state.Message{ 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 0b20fb655..ec9c7e74e 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 @@ -308,12 +308,11 @@ var opCodeToString = map[OpCode]string{ SWAP14: "SWAP14", SWAP15: "SWAP15", SWAP16: "SWAP16", - - LOG0: "LOG0", - LOG1: "LOG1", - LOG2: "LOG2", - LOG3: "LOG3", - LOG4: "LOG4", + 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 0a95953b0..31345c555 100644 --- a/vm/vm_debug.go +++ b/vm/vm_debug.go @@ -41,7 +41,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) { @@ -177,10 +177,13 @@ func (self *DebugVm) Run(call Options) (ret []byte, gas *big.Int, err error) { n := int(op - LOG0) require(n + 2) - mSize, mStart := stack.Peekn() - reqGs.Set(GasLog) + gas.Set(GasLog) addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog)) - addStepGasUsage(new(big.Int).Add(mSize, mStart)) + + mSize, mStart := stack.Peekn() + addStepGasUsage(mSize) + + newMemSize = calcMemSize(mStart, mSize) case EXP: require(2) @@ -762,10 +765,10 @@ func (self *DebugVm) Run(call Options) (ret []byte, gas *big.Int, 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}