core/state, core/vm: reworked storage get / set to use common.Hash
This commit is contained in:
		@@ -62,6 +62,10 @@ func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
 | 
				
			|||||||
	return reflect.ValueOf(h)
 | 
						return reflect.ValueOf(h)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func EmptyHash(h Hash) bool {
 | 
				
			||||||
 | 
						return h == Hash{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/////////// Address
 | 
					/////////// Address
 | 
				
			||||||
func BytesToAddress(b []byte) Address {
 | 
					func BytesToAddress(b []byte) Address {
 | 
				
			||||||
	var a Address
 | 
						var a Address
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,11 +19,11 @@ func (self Code) String() string {
 | 
				
			|||||||
	return string(self) //strings.Join(Disassemble(self), " ")
 | 
						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) {
 | 
					func (self Storage) String() (str string) {
 | 
				
			||||||
	for key, value := range self {
 | 
						for key, value := range self {
 | 
				
			||||||
		str += fmt.Sprintf("%X : %X\n", key, value.Bytes())
 | 
							str += fmt.Sprintf("%X : %X\n", key, value)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
@@ -32,7 +32,6 @@ func (self Storage) String() (str string) {
 | 
				
			|||||||
func (self Storage) Copy() Storage {
 | 
					func (self Storage) Copy() Storage {
 | 
				
			||||||
	cpy := make(Storage)
 | 
						cpy := make(Storage)
 | 
				
			||||||
	for key, value := range self {
 | 
						for key, value := range self {
 | 
				
			||||||
		// XXX Do we need a 'value' copy or is this sufficient?
 | 
					 | 
				
			||||||
		cpy[key] = value
 | 
							cpy[key] = value
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,7 +111,7 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data
 | 
				
			|||||||
	object.balance = extobject.Balance
 | 
						object.balance = extobject.Balance
 | 
				
			||||||
	object.codeHash = extobject.CodeHash
 | 
						object.codeHash = extobject.CodeHash
 | 
				
			||||||
	object.State = New(extobject.Root, db)
 | 
						object.State = New(extobject.Root, db)
 | 
				
			||||||
	object.storage = make(map[string]*common.Value)
 | 
						object.storage = make(map[string]common.Hash)
 | 
				
			||||||
	object.gasPool = new(big.Int)
 | 
						object.gasPool = new(big.Int)
 | 
				
			||||||
	object.prepaid = new(big.Int)
 | 
						object.prepaid = new(big.Int)
 | 
				
			||||||
	object.code, _ = db.Get(extobject.CodeHash)
 | 
						object.code, _ = db.Get(extobject.CodeHash)
 | 
				
			||||||
@@ -129,35 +128,29 @@ func (self *StateObject) MarkForDeletion() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *StateObject) getAddr(addr common.Hash) *common.Value {
 | 
					func (c *StateObject) getAddr(addr common.Hash) (ret common.Hash) {
 | 
				
			||||||
	return common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:])))
 | 
						return common.BytesToHash(common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:]))).Bytes())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *StateObject) setAddr(addr []byte, value interface{}) {
 | 
					func (c *StateObject) setAddr(addr []byte, value common.Hash) {
 | 
				
			||||||
	c.State.trie.Update(addr, common.Encode(value))
 | 
						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.State.trie.Update(addr, v)
 | 
				
			||||||
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 (self *StateObject) Storage() Storage {
 | 
					func (self *StateObject) Storage() Storage {
 | 
				
			||||||
	return self.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()
 | 
						strkey := key.Str()
 | 
				
			||||||
	value := self.storage[strkey]
 | 
						value, exists := self.storage[strkey]
 | 
				
			||||||
	if value == nil {
 | 
						if !exists {
 | 
				
			||||||
		value = self.getAddr(key)
 | 
							value = self.getAddr(key)
 | 
				
			||||||
 | 
							if (value != common.Hash{}) {
 | 
				
			||||||
		if !value.IsNil() {
 | 
					 | 
				
			||||||
			self.storage[strkey] = value
 | 
								self.storage[strkey] = value
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -165,14 +158,14 @@ func (self *StateObject) GetState(key common.Hash) *common.Value {
 | 
				
			|||||||
	return value
 | 
						return value
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) SetState(k common.Hash, value *common.Value) {
 | 
					func (self *StateObject) SetState(k, value common.Hash) {
 | 
				
			||||||
	self.storage[k.Str()] = value.Copy()
 | 
						self.storage[k.Str()] = value
 | 
				
			||||||
	self.dirty = true
 | 
						self.dirty = true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateObject) Sync() {
 | 
					func (self *StateObject) Sync() {
 | 
				
			||||||
	for key, value := range self.storage {
 | 
						for key, value := range self.storage {
 | 
				
			||||||
		if value.Len() == 0 {
 | 
							if (value == common.Hash{}) {
 | 
				
			||||||
			self.State.trie.Delete([]byte(key))
 | 
								self.State.trie.Delete([]byte(key))
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -370,7 +363,7 @@ func (c *StateObject) RlpDecode(data []byte) {
 | 
				
			|||||||
	c.nonce = decoder.Get(0).Uint()
 | 
						c.nonce = decoder.Get(0).Uint()
 | 
				
			||||||
	c.balance = decoder.Get(1).BigInt()
 | 
						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.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.storage = make(map[string]common.Hash)
 | 
				
			||||||
	c.gasPool = new(big.Int)
 | 
						c.gasPool = new(big.Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.codeHash = decoder.Get(3).Bytes()
 | 
						c.codeHash = decoder.Get(3).Bytes()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,13 +103,13 @@ func (self *StateDB) GetCode(addr common.Address) []byte {
 | 
				
			|||||||
	return nil
 | 
						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)
 | 
						stateObject := self.GetStateObject(a)
 | 
				
			||||||
	if stateObject != nil {
 | 
						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 {
 | 
					func (self *StateDB) IsDeleted(addr common.Address) bool {
 | 
				
			||||||
@@ -145,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)
 | 
						stateObject := self.GetOrNewStateObject(addr)
 | 
				
			||||||
	if stateObject != nil {
 | 
						if stateObject != nil {
 | 
				
			||||||
		stateObject.SetState(key, common.NewValue(value))
 | 
							stateObject.SetState(key, value)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -506,14 +506,14 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		case SLOAD:
 | 
							case SLOAD:
 | 
				
			||||||
			loc := common.BigToHash(stack.pop())
 | 
								loc := common.BigToHash(stack.pop())
 | 
				
			||||||
			val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
 | 
								val := statedb.GetState(context.Address(), loc).Big()
 | 
				
			||||||
			stack.push(val)
 | 
								stack.push(val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case SSTORE:
 | 
							case SSTORE:
 | 
				
			||||||
			loc := common.BigToHash(stack.pop())
 | 
								loc := common.BigToHash(stack.pop())
 | 
				
			||||||
			val := stack.pop()
 | 
								val := stack.pop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			statedb.SetState(context.Address(), loc, val)
 | 
								statedb.SetState(context.Address(), loc, common.BigToHash(val))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case JUMP:
 | 
							case JUMP:
 | 
				
			||||||
			if err := jump(pc, stack.pop()); err != nil {
 | 
								if err := jump(pc, stack.pop()); err != nil {
 | 
				
			||||||
@@ -686,10 +686,10 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
 | 
				
			|||||||
		var g *big.Int
 | 
							var g *big.Int
 | 
				
			||||||
		y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
 | 
							y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
 | 
				
			||||||
		val := statedb.GetState(context.Address(), common.BigToHash(x))
 | 
							val := statedb.GetState(context.Address(), common.BigToHash(x))
 | 
				
			||||||
		if len(val) == 0 && len(y.Bytes()) > 0 {
 | 
							if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
 | 
				
			||||||
			// 0 => non 0
 | 
								// 0 => non 0
 | 
				
			||||||
			g = params.SstoreSetGas
 | 
								g = params.SstoreSetGas
 | 
				
			||||||
		} else if len(val) > 0 && len(y.Bytes()) == 0 {
 | 
							} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
 | 
				
			||||||
			statedb.Refund(params.SstoreRefundGas)
 | 
								statedb.Refund(params.SstoreRefundGas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			g = params.SstoreClearGas
 | 
								g = params.SstoreClearGas
 | 
				
			||||||
@@ -697,6 +697,13 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
 | 
				
			|||||||
			// non 0 => non 0 (or 0 => 0)
 | 
								// non 0 => non 0 (or 0 => 0)
 | 
				
			||||||
			g = params.SstoreClearGas
 | 
								g = params.SstoreClearGas
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
								if len(val) == 0 && len(y.Bytes()) > 0 {
 | 
				
			||||||
 | 
								} else if len(val) > 0 && len(y.Bytes()) == 0 {
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
		gas.Set(g)
 | 
							gas.Set(g)
 | 
				
			||||||
	case SUICIDE:
 | 
						case SUICIDE:
 | 
				
			||||||
		if !statedb.IsDeleted(context.Address()) {
 | 
							if !statedb.IsDeleted(context.Address()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,7 +97,7 @@ func RunVmTest(p string, t *testing.T) {
 | 
				
			|||||||
			obj := StateObjectFromAccount(db, addr, account)
 | 
								obj := StateObjectFromAccount(db, addr, account)
 | 
				
			||||||
			statedb.SetStateObject(obj)
 | 
								statedb.SetStateObject(obj)
 | 
				
			||||||
			for a, v := range account.Storage {
 | 
								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 {
 | 
								for addr, value := range account.Storage {
 | 
				
			||||||
				v := obj.GetState(common.HexToHash(addr)).Bytes()
 | 
									v := obj.GetState(common.HexToHash(addr))
 | 
				
			||||||
				vexp := helper.FromHex(value)
 | 
									vexp := common.HexToHash(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if bytes.Compare(v, vexp) != 0 {
 | 
									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, common.BigD(vexp), common.BigD(v))
 | 
										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())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user