diff --git a/common/types.go b/common/types.go index d05c21eecc..e41112a77a 100644 --- a/common/types.go +++ b/common/types.go @@ -62,6 +62,10 @@ func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { return reflect.ValueOf(h) } +func EmptyHash(h Hash) bool { + return h == Hash{} +} + /////////// Address func BytesToAddress(b []byte) Address { var a Address diff --git a/core/block_processor.go b/core/block_processor.go index c01b110be0..c78d419ce3 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -185,7 +185,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st state := state.New(parent.Root(), sm.db) // Block validation - if err = sm.ValidateHeader(block.Header(), parent.Header(), false); err != nil { + if err = ValidateHeader(sm.Pow, block.Header(), parent.Header(), false); err != nil { return } @@ -246,12 +246,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st return } - // store the receipts - err = putReceipts(sm.extraDb, block.Hash(), receipts) - if err != nil { - return nil, err - } - // Sync the current block's state to the database state.Sync() @@ -260,76 +254,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st putTx(sm.extraDb, tx, block, uint64(i)) } - receiptsRlp := receipts.RlpEncode() - /*if len(receipts) > 0 { - glog.V(logger.Info).Infof("Saving %v receipts, rlp len is %v\n", len(receipts), len(receiptsRlp)) - }*/ - sm.extraDb.Put(append(receiptsPre, block.Hash().Bytes()...), receiptsRlp) + // store the receipts + putReceipts(sm.extraDb, block.Hash(), receipts) return state.Logs(), nil } -// See YP section 4.3.4. "Block Header Validity" -// Validates a block. Returns an error if the block is invalid. -func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error { - if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 { - return fmt.Errorf("Block extra data too long (%d)", len(block.Extra)) - } - - expd := CalcDifficulty(block, parent) - if expd.Cmp(block.Difficulty) != 0 { - return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) - } - - a := new(big.Int).Sub(block.GasLimit, parent.GasLimit) - a.Abs(a) - b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor) - if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) { - return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b) - } - - if int64(block.Time) > time.Now().Unix() { - return BlockFutureErr - } - - if new(big.Int).Sub(block.Number, parent.Number).Cmp(big.NewInt(1)) != 0 { - return BlockNumberErr - } - - if block.Time <= parent.Time { - return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time) - } - - if checkPow { - // Verify the nonce of the block. Return an error if it's not valid - if !sm.Pow.Verify(types.NewBlockWithHeader(block)) { - return ValidationError("Block's nonce is invalid (= %x)", block.Nonce) - } - } - - return nil -} - -func AccumulateRewards(statedb *state.StateDB, block *types.Block) { - reward := new(big.Int).Set(BlockReward) - - for _, uncle := range block.Uncles() { - num := new(big.Int).Add(big.NewInt(8), uncle.Number) - num.Sub(num, block.Number()) - - r := new(big.Int) - r.Mul(BlockReward, num) - r.Div(r, big.NewInt(8)) - - statedb.AddBalance(uncle.Coinbase, r) - - reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) - } - - // Get the account associated with the coinbase - statedb.AddBalance(block.Header().Coinbase, reward) -} - func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error { ancestors := set.New() uncles := set.New() @@ -367,7 +297,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4]) } - if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash], true); err != nil { + if err := ValidateHeader(sm.Pow, uncle, ancestorHeaders[uncle.ParentHash], true); err != nil { return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err)) } } @@ -404,6 +334,67 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro return state.Logs(), nil } +// See YP section 4.3.4. "Block Header Validity" +// Validates a block. Returns an error if the block is invalid. +func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) error { + if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 { + return fmt.Errorf("Block extra data too long (%d)", len(block.Extra)) + } + + expd := CalcDifficulty(block, parent) + if expd.Cmp(block.Difficulty) != 0 { + return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) + } + + a := new(big.Int).Sub(block.GasLimit, parent.GasLimit) + a.Abs(a) + b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor) + if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) { + return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b) + } + + if int64(block.Time) > time.Now().Unix() { + return BlockFutureErr + } + + if new(big.Int).Sub(block.Number, parent.Number).Cmp(big.NewInt(1)) != 0 { + return BlockNumberErr + } + + if block.Time <= parent.Time { + return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time) + } + + if checkPow { + // Verify the nonce of the block. Return an error if it's not valid + if !pow.Verify(types.NewBlockWithHeader(block)) { + return ValidationError("Block's nonce is invalid (= %x)", block.Nonce) + } + } + + return nil +} + +func AccumulateRewards(statedb *state.StateDB, block *types.Block) { + reward := new(big.Int).Set(BlockReward) + + for _, uncle := range block.Uncles() { + num := new(big.Int).Add(big.NewInt(8), uncle.Number) + num.Sub(num, block.Number()) + + r := new(big.Int) + r.Mul(BlockReward, num) + r.Div(r, big.NewInt(8)) + + statedb.AddBalance(uncle.Coinbase, r) + + reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32))) + } + + // Get the account associated with the coinbase + statedb.AddBalance(block.Header().Coinbase, reward) +} + func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) { var rdata []byte rdata, err = db.Get(append(receiptsPre, bhash[:]...)) diff --git a/core/block_processor_test.go b/core/block_processor_test.go index 97b80038dc..e38c815efe 100644 --- a/core/block_processor_test.go +++ b/core/block_processor_test.go @@ -26,18 +26,20 @@ func proc() (*BlockProcessor, *ChainManager) { } func TestNumber(t *testing.T) { - bp, chain := proc() + _, chain := proc() block1 := chain.NewBlock(common.Address{}) block1.Header().Number = big.NewInt(3) block1.Header().Time-- - err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false) + pow := ezp.New() + + err := ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false) if err != BlockNumberErr { t.Errorf("expected block number error %v", err) } block1 = chain.NewBlock(common.Address{}) - err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false) + err = ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false) if err == BlockNumberErr { t.Errorf("didn't expect block number error") } diff --git a/core/state/dump.go b/core/state/dump.go index 70ea216914..f6f2f90297 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -34,7 +34,7 @@ func (self *StateDB) RawDump() World { account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash)} account.Storage = make(map[string]string) - storageIt := stateObject.State.trie.Iterator() + storageIt := stateObject.trie.Iterator() for storageIt.Next() { account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value) } @@ -54,8 +54,8 @@ func (self *StateDB) Dump() []byte { // Debug stuff func (self *StateObject) CreateOutputForDiff() { - fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.nonce) - it := self.State.trie.Iterator() + fmt.Printf("%x %x %x %x\n", self.Address(), self.Root(), self.balance.Bytes(), self.nonce) + it := self.trie.Iterator() for it.Next() { fmt.Printf("%x %x\n", it.Key, it.Value) } diff --git a/core/state/state_object.go b/core/state/state_object.go index 6d2455d792..2e4fe32690 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -19,11 +19,11 @@ func (self Code) String() string { return string(self) //strings.Join(Disassemble(self), " ") } -type Storage map[string]*common.Value +type Storage map[string]common.Hash func (self Storage) String() (str string) { for key, value := range self { - str += fmt.Sprintf("%X : %X\n", key, value.Bytes()) + str += fmt.Sprintf("%X : %X\n", key, value) } return @@ -32,7 +32,6 @@ func (self Storage) String() (str string) { func (self Storage) Copy() Storage { cpy := make(Storage) for key, value := range self { - // XXX Do we need a 'value' copy or is this sufficient? cpy[key] = value } @@ -41,9 +40,8 @@ func (self Storage) Copy() Storage { type StateObject struct { // State database for storing state changes - db common.Database - // The state object - State *StateDB + db common.Database + trie *trie.SecureTrie // Address belonging to this account address common.Address @@ -76,7 +74,6 @@ type StateObject struct { func (self *StateObject) Reset() { self.storage = make(Storage) - self.State.Reset() } func NewStateObject(address common.Address, db common.Database) *StateObject { @@ -84,7 +81,7 @@ func NewStateObject(address common.Address, db common.Database) *StateObject { //address := common.ToAddress(addr) object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true} - object.State = New(common.Hash{}, db) //New(trie.New(common.Config.Db, "")) + object.trie = trie.NewSecure((common.Hash{}).Bytes(), db) object.storage = make(Storage) object.gasPool = new(big.Int) object.prepaid = new(big.Int) @@ -111,8 +108,8 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data object.nonce = extobject.Nonce object.balance = extobject.Balance object.codeHash = extobject.CodeHash - object.State = New(extobject.Root, db) - object.storage = make(map[string]*common.Value) + object.trie = trie.NewSecure(extobject.Root[:], db) + object.storage = make(map[string]common.Hash) object.gasPool = new(big.Int) object.prepaid = new(big.Int) object.code, _ = db.Get(extobject.CodeHash) @@ -129,35 +126,31 @@ func (self *StateObject) MarkForDeletion() { } } -func (c *StateObject) getAddr(addr common.Hash) *common.Value { - return common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:]))) +func (c *StateObject) getAddr(addr common.Hash) common.Hash { + var ret []byte + rlp.DecodeBytes(c.trie.Get(addr[:]), &ret) + return common.BytesToHash(ret) } -func (c *StateObject) setAddr(addr []byte, value interface{}) { - c.State.trie.Update(addr, common.Encode(value)) -} - -func (self *StateObject) GetStorage(key *big.Int) *common.Value { - fmt.Printf("%v: get %v %v", self.address.Hex(), key) - return self.GetState(common.BytesToHash(key.Bytes())) -} - -func (self *StateObject) SetStorage(key *big.Int, value *common.Value) { - fmt.Printf("%v: set %v -> %v", self.address.Hex(), key, value) - self.SetState(common.BytesToHash(key.Bytes()), value) +func (c *StateObject) setAddr(addr []byte, value common.Hash) { + v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) + if err != nil { + // if RLPing failed we better panic and not fail silently. This would be considered a consensus issue + panic(err) + } + c.trie.Update(addr, v) } func (self *StateObject) Storage() Storage { return self.storage } -func (self *StateObject) GetState(key common.Hash) *common.Value { +func (self *StateObject) GetState(key common.Hash) common.Hash { strkey := key.Str() - value := self.storage[strkey] - if value == nil { + value, exists := self.storage[strkey] + if !exists { value = self.getAddr(key) - - if !value.IsNil() { + if (value != common.Hash{}) { self.storage[strkey] = value } } @@ -165,15 +158,16 @@ func (self *StateObject) GetState(key common.Hash) *common.Value { return value } -func (self *StateObject) SetState(k common.Hash, value *common.Value) { - self.storage[k.Str()] = value.Copy() +func (self *StateObject) SetState(k, value common.Hash) { + self.storage[k.Str()] = value self.dirty = true } -func (self *StateObject) Sync() { +// Update updates the current cached storage to the trie +func (self *StateObject) Update() { for key, value := range self.storage { - if value.Len() == 0 { - self.State.trie.Delete([]byte(key)) + if (value == common.Hash{}) { + self.trie.Delete([]byte(key)) continue } @@ -266,9 +260,7 @@ func (self *StateObject) Copy() *StateObject { stateObject.balance.Set(self.balance) stateObject.codeHash = common.CopyBytes(self.codeHash) stateObject.nonce = self.nonce - if self.State != nil { - stateObject.State = self.State.Copy() - } + stateObject.trie = self.trie stateObject.code = common.CopyBytes(self.code) stateObject.initCode = common.CopyBytes(self.initCode) stateObject.storage = self.storage.Copy() @@ -306,11 +298,11 @@ func (c *StateObject) Init() Code { } func (self *StateObject) Trie() *trie.SecureTrie { - return self.State.trie + return self.trie } func (self *StateObject) Root() []byte { - return self.Trie().Root() + return self.trie.Root() } func (self *StateObject) Code() []byte { @@ -342,10 +334,10 @@ func (self *StateObject) EachStorage(cb func(key, value []byte)) { cb([]byte(h), v.Bytes()) } - it := self.State.trie.Iterator() + it := self.trie.Iterator() for it.Next() { // ignore cached values - key := self.State.trie.GetKey(it.Key) + key := self.trie.GetKey(it.Key) if _, ok := self.storage[string(key)]; !ok { cb(key, it.Value) } @@ -369,8 +361,8 @@ func (c *StateObject) RlpDecode(data []byte) { decoder := common.NewValueFromBytes(data) c.nonce = decoder.Get(0).Uint() c.balance = decoder.Get(1).BigInt() - c.State = New(common.BytesToHash(decoder.Get(2).Bytes()), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface())) - c.storage = make(map[string]*common.Value) + c.trie = trie.NewSecure(decoder.Get(2).Bytes(), c.db) + c.storage = make(map[string]common.Hash) c.gasPool = new(big.Int) c.codeHash = decoder.Get(3).Bytes() diff --git a/core/state/state_test.go b/core/state/state_test.go index 09a65de54c..00e133dabf 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -70,37 +70,34 @@ func TestNull(t *testing.T) { address := common.HexToAddress("0x823140710bf13990e4500136726d8b55") state.CreateAccount(address) //value := common.FromHex("0x823140710bf13990e4500136726d8b55") - value := make([]byte, 16) + var value common.Hash state.SetState(address, common.Hash{}, value) state.Update() state.Sync() value = state.GetState(address, common.Hash{}) + if !common.EmptyHash(value) { + t.Errorf("expected empty hash. got %x", value) + } } func (s *StateSuite) TestSnapshot(c *checker.C) { stateobjaddr := toAddr([]byte("aa")) - storageaddr := common.Big("0") - data1 := common.NewValue(42) - data2 := common.NewValue(43) + var storageaddr common.Hash + data1 := common.BytesToHash([]byte{42}) + data2 := common.BytesToHash([]byte{43}) - // get state object - stateObject := s.state.GetOrNewStateObject(stateobjaddr) // set inital state object value - stateObject.SetStorage(storageaddr, data1) + s.state.SetState(stateobjaddr, storageaddr, data1) // get snapshot of current state snapshot := s.state.Copy() - // get state object. is this strictly necessary? - stateObject = s.state.GetStateObject(stateobjaddr) // set new state object value - stateObject.SetStorage(storageaddr, data2) + s.state.SetState(stateobjaddr, storageaddr, data2) // restore snapshot s.state.Set(snapshot) - // get state object - stateObject = s.state.GetStateObject(stateobjaddr) // get state storage value - res := stateObject.GetStorage(storageaddr) + res := s.state.GetState(stateobjaddr, storageaddr) c.Assert(data1, checker.DeepEquals, res) } diff --git a/core/state/statedb.go b/core/state/statedb.go index b3050515b6..f6f63f329c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -21,7 +21,7 @@ type StateDB struct { stateObjects map[string]*StateObject - refund map[string]*big.Int + refund *big.Int thash, bhash common.Hash txIndex int @@ -31,7 +31,7 @@ type StateDB struct { // Create a new state from a given trie func New(root common.Hash, db common.Database) *StateDB { trie := trie.NewSecure(root[:], db) - return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int), logs: make(map[common.Hash]Logs)} + return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} } func (self *StateDB) PrintRoot() { @@ -63,12 +63,8 @@ func (self *StateDB) Logs() Logs { return logs } -func (self *StateDB) Refund(address common.Address, gas *big.Int) { - addr := address.Str() - if self.refund[addr] == nil { - self.refund[addr] = new(big.Int) - } - self.refund[addr].Add(self.refund[addr], gas) +func (self *StateDB) Refund(gas *big.Int) { + self.refund.Add(self.refund, gas) } /* @@ -107,13 +103,13 @@ func (self *StateDB) GetCode(addr common.Address) []byte { return nil } -func (self *StateDB) GetState(a common.Address, b common.Hash) []byte { +func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { stateObject := self.GetStateObject(a) if stateObject != nil { - return stateObject.GetState(b).Bytes() + return stateObject.GetState(b) } - return nil + return common.Hash{} } func (self *StateDB) IsDeleted(addr common.Address) bool { @@ -149,10 +145,10 @@ func (self *StateDB) SetCode(addr common.Address, code []byte) { } } -func (self *StateDB) SetState(addr common.Address, key common.Hash, value interface{}) { +func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { - stateObject.SetState(key, common.NewValue(value)) + stateObject.SetState(key, value) } } @@ -263,14 +259,12 @@ func (s *StateDB) Cmp(other *StateDB) bool { func (self *StateDB) Copy() *StateDB { state := New(common.Hash{}, self.db) - state.trie = self.trie.Copy() + state.trie = self.trie for k, stateObject := range self.stateObjects { state.stateObjects[k] = stateObject.Copy() } - for addr, refund := range self.refund { - state.refund[addr] = new(big.Int).Set(refund) - } + state.refund.Set(self.refund) for hash, logs := range self.logs { state.logs[hash] = make(Logs, len(logs)) @@ -302,10 +296,6 @@ func (s *StateDB) Reset() { // Reset all nested states for _, stateObject := range s.stateObjects { - if stateObject.State == nil { - continue - } - stateObject.Reset() } @@ -316,11 +306,7 @@ func (s *StateDB) Reset() { func (s *StateDB) Sync() { // Sync all nested states for _, stateObject := range s.stateObjects { - if stateObject.State == nil { - continue - } - - stateObject.State.Sync() + stateObject.trie.Commit() } s.trie.Commit() @@ -330,22 +316,22 @@ func (s *StateDB) Sync() { func (self *StateDB) Empty() { self.stateObjects = make(map[string]*StateObject) - self.refund = make(map[string]*big.Int) + self.refund = new(big.Int) } -func (self *StateDB) Refunds() map[string]*big.Int { +func (self *StateDB) Refunds() *big.Int { return self.refund } func (self *StateDB) Update() { - self.refund = make(map[string]*big.Int) + self.refund = new(big.Int) for _, stateObject := range self.stateObjects { if stateObject.dirty { if stateObject.remove { self.DeleteStateObject(stateObject) } else { - stateObject.Sync() + stateObject.Update() self.UpdateStateObject(stateObject) } diff --git a/core/state_transition.go b/core/state_transition.go index fedea8021e..4a8d92375a 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -241,11 +241,9 @@ func (self *StateTransition) refundGas() { sender.AddBalance(remaining) uhalf := new(big.Int).Div(self.gasUsed(), common.Big2) - for addr, ref := range self.state.Refunds() { - refund := common.BigMin(uhalf, ref) - self.gas.Add(self.gas, refund) - self.state.AddBalance(common.StringToAddress(addr), refund.Mul(refund, self.msg.GasPrice())) - } + refund := common.BigMin(uhalf, self.state.Refunds()) + self.gas.Add(self.gas, refund) + self.state.AddBalance(sender.Address(), refund.Mul(refund, self.msg.GasPrice())) coinbase.RefundGas(self.gas, self.msg.GasPrice()) } diff --git a/core/transaction_pool.go b/core/transaction_pool.go index e31f5c6b3e..5ebe3576bb 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -105,7 +105,9 @@ func (pool *TxPool) resetState() { if addr, err := tx.From(); err == nil { // Set the nonce. Transaction nonce can never be lower // than the state nonce; validatePool took care of that. - pool.pendingState.SetNonce(addr, tx.Nonce()) + if pool.pendingState.GetNonce(addr) < tx.Nonce() { + pool.pendingState.SetNonce(addr, tx.Nonce()) + } } } @@ -153,6 +155,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error { return ErrNonExistentAccount } + // Last but not least check for nonce errors + if pool.currentState().GetNonce(from) > tx.Nonce() { + return ErrNonce + } + // Check the transaction doesn't exceed the current // block limit gas. if pool.gasLimit().Cmp(tx.GasLimit) < 0 { @@ -179,12 +186,6 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error { return ErrIntrinsicGas } - // Last but not least check for nonce errors (intensive - // operation, saved for last) - if pool.currentState().GetNonce(from) > tx.Nonce() { - return ErrNonce - } - return nil } @@ -394,10 +395,13 @@ func (pool *TxPool) removeTx(hash common.Hash) { // validatePool removes invalid and processed transactions from the main pool. func (pool *TxPool) validatePool() { + state := pool.currentState() for hash, tx := range pool.pending { - if err := pool.validateTx(tx); err != nil { + from, _ := tx.From() // err already checked + // perform light nonce validation + if state.GetNonce(from) > tx.Nonce() { if glog.V(logger.Core) { - glog.Infof("removed tx (%x) from pool: %v\n", hash[:4], err) + glog.Infof("removed tx (%x) from pool: low tx nonce\n", hash[:4]) } delete(pool.pending, hash) } diff --git a/core/vm/vm.go b/core/vm/vm.go index c5ad761f64..9e092300de 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -506,14 +506,14 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) { case SLOAD: loc := common.BigToHash(stack.pop()) - val := common.Bytes2Big(statedb.GetState(context.Address(), loc)) + val := statedb.GetState(context.Address(), loc).Big() stack.push(val) case SSTORE: loc := common.BigToHash(stack.pop()) val := stack.pop() - statedb.SetState(context.Address(), loc, val) + statedb.SetState(context.Address(), loc, common.BigToHash(val)) case JUMP: if err := jump(pc, stack.pop()); err != nil { @@ -686,11 +686,16 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo var g *big.Int y, x := stack.data[stack.len()-2], stack.data[stack.len()-1] val := statedb.GetState(context.Address(), common.BigToHash(x)) - if len(val) == 0 && len(y.Bytes()) > 0 { + + // This checks for 3 scenario's and calculates gas accordingly + // 1. From a zero-value address to a non-zero value (NEW VALUE) + // 2. From a non-zero value address to a zero-value address (DELETE) + // 3. From a nen-zero to a non-zero (CHANGE) + if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) { // 0 => non 0 g = params.SstoreSetGas - } else if len(val) > 0 && len(y.Bytes()) == 0 { - statedb.Refund(self.env.Origin(), params.SstoreRefundGas) + } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) { + statedb.Refund(params.SstoreRefundGas) g = params.SstoreClearGas } else { @@ -700,7 +705,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo gas.Set(g) case SUICIDE: if !statedb.IsDeleted(context.Address()) { - statedb.Refund(self.env.Origin(), params.SuicideRefundGas) + statedb.Refund(params.SuicideRefundGas) } case MLOAD: newMemSize = calcMemSize(stack.peek(), u256(32)) diff --git a/tests/block_test_util.go b/tests/block_test_util.go index ae2ae40331..200fcbd599 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -124,7 +124,7 @@ func (t *BlockTest) InsertPreState(ethereum *eth.Ethereum) (*state.StateDB, erro obj.SetBalance(balance) obj.SetNonce(nonce) for k, v := range acct.Storage { - statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.FromHex(v)) + statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v)) } } // sync objects to trie diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go index a95d02576a..be9e89d9c0 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -97,7 +97,7 @@ func RunVmTest(p string, t *testing.T) { obj := StateObjectFromAccount(db, addr, account) statedb.SetStateObject(obj) for a, v := range account.Storage { - obj.SetState(common.HexToHash(a), common.NewValue(helper.FromHex(v))) + obj.SetState(common.HexToHash(a), common.HexToHash(v)) } } @@ -168,11 +168,11 @@ func RunVmTest(p string, t *testing.T) { } for addr, value := range account.Storage { - v := obj.GetState(common.HexToHash(addr)).Bytes() - vexp := helper.FromHex(value) + v := obj.GetState(common.HexToHash(addr)) + vexp := common.HexToHash(value) - if bytes.Compare(v, vexp) != 0 { - t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address().Bytes()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v)) + if v != vexp { + t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big()) } } } diff --git a/xeth/types.go b/xeth/types.go index 3bb1447ca5..ed64dc45ec 100644 --- a/xeth/types.go +++ b/xeth/types.go @@ -22,7 +22,7 @@ func NewObject(state *state.StateObject) *Object { return &Object{state} } -func (self *Object) StorageString(str string) *common.Value { +func (self *Object) StorageString(str string) []byte { if common.IsHex(str) { return self.storage(common.Hex2Bytes(str[2:])) } else { @@ -30,12 +30,12 @@ func (self *Object) StorageString(str string) *common.Value { } } -func (self *Object) StorageValue(addr *common.Value) *common.Value { +func (self *Object) StorageValue(addr *common.Value) []byte { return self.storage(addr.Bytes()) } -func (self *Object) storage(addr []byte) *common.Value { - return self.StateObject.GetStorage(common.BigD(addr)) +func (self *Object) storage(addr []byte) []byte { + return self.StateObject.GetState(common.BytesToHash(addr)).Bytes() } func (self *Object) Storage() (storage map[string]string) { diff --git a/xeth/xeth.go b/xeth/xeth.go index 71753d6bd7..d68f48d505 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -488,7 +488,7 @@ func (self *XEth) NumberToHuman(balance string) string { } func (self *XEth) StorageAt(addr, storageAddr string) string { - return common.ToHex(self.State().state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr))) + return self.State().state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex() } func (self *XEth) BalanceAt(addr string) string {