Trie fixes
This commit is contained in:
		| @@ -76,6 +76,8 @@ func (self *State) DeleteStateObject(stateObject *StateObject) { | |||||||
|  |  | ||||||
| // Retrieve a state object given my the address. Nil if not found | // Retrieve a state object given my the address. Nil if not found | ||||||
| func (self *State) GetStateObject(addr []byte) *StateObject { | func (self *State) GetStateObject(addr []byte) *StateObject { | ||||||
|  | 	addr = ethutil.Address(addr) | ||||||
|  |  | ||||||
| 	stateObject := self.stateObjects[string(addr)] | 	stateObject := self.stateObjects[string(addr)] | ||||||
| 	if stateObject != nil { | 	if stateObject != nil { | ||||||
| 		return stateObject | 		return stateObject | ||||||
| @@ -204,6 +206,8 @@ func (self *State) Update() { | |||||||
| 	// FIXME trie delete is broken | 	// FIXME trie delete is broken | ||||||
| 	valid, t2 := ethtrie.ParanoiaCheck(self.trie) | 	valid, t2 := ethtrie.ParanoiaCheck(self.trie) | ||||||
| 	if !valid { | 	if !valid { | ||||||
|  | 		statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root, t2.Root) | ||||||
|  |  | ||||||
| 		self.trie = t2 | 		self.trie = t2 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -121,6 +121,7 @@ done: | |||||||
| 	for i, tx := range txs { | 	for i, tx := range txs { | ||||||
| 		txGas := new(big.Int).Set(tx.Gas) | 		txGas := new(big.Int).Set(tx.Gas) | ||||||
| 		st := NewStateTransition(coinbase, tx, state, block) | 		st := NewStateTransition(coinbase, tx, state, block) | ||||||
|  | 		//fmt.Printf("#%d\n", i+1) | ||||||
| 		err = st.TransitionState() | 		err = st.TransitionState() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			switch { | 			switch { | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ func MakeContract(tx *Transaction, state *State) *StateObject { | |||||||
|  |  | ||||||
| func NewStateObject(addr []byte) *StateObject { | func NewStateObject(addr []byte) *StateObject { | ||||||
| 	// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter. | 	// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter. | ||||||
| 	address := ethutil.LeftPadBytes(addr, 20) | 	address := ethutil.Address(addr) | ||||||
|  |  | ||||||
| 	object := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)} | 	object := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)} | ||||||
| 	object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) | 	object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) | ||||||
| @@ -92,13 +92,6 @@ func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject { | |||||||
| 	return contract | 	return contract | ||||||
| } | } | ||||||
|  |  | ||||||
| // Returns a newly created account |  | ||||||
| func NewAccount(address []byte, amount *big.Int) *StateObject { |  | ||||||
| 	account := &StateObject{address: address, Amount: amount, Nonce: 0} |  | ||||||
|  |  | ||||||
| 	return account |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func NewStateObjectFromBytes(address, data []byte) *StateObject { | func NewStateObjectFromBytes(address, data []byte) *StateObject { | ||||||
| 	object := &StateObject{address: address} | 	object := &StateObject{address: address} | ||||||
| 	object.RlpDecode(data) | 	object.RlpDecode(data) | ||||||
| @@ -139,17 +132,37 @@ func (self *StateObject) getStorage(k []byte) *ethutil.Value { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return value | 	return value | ||||||
|  |  | ||||||
|  | 	//return self.GetAddr(key) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *StateObject) setStorage(k []byte, value *ethutil.Value) { | func (self *StateObject) setStorage(k []byte, value *ethutil.Value) { | ||||||
| 	key := ethutil.LeftPadBytes(k, 32) | 	key := ethutil.LeftPadBytes(k, 32) | ||||||
| 	//fmt.Printf("%x %v\n", key, value) |  | ||||||
| 	self.storage[string(key)] = value.Copy() | 	self.storage[string(key)] = value.Copy() | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 		if value.BigInt().Cmp(ethutil.Big0) == 0 { | ||||||
|  | 			self.state.trie.Delete(string(key)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		self.SetAddr(key, value) | ||||||
|  | 	*/ | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *StateObject) Sync() { | func (self *StateObject) Sync() { | ||||||
|  | 	/* | ||||||
|  | 		fmt.Println("############# BEFORE ################") | ||||||
|  | 		self.state.EachStorage(func(key string, value *ethutil.Value) { | ||||||
|  | 			fmt.Printf("%x %x %x\n", self.Address(), []byte(key), value.Bytes()) | ||||||
|  | 		}) | ||||||
|  | 		fmt.Printf("%x @:%x\n", self.Address(), self.state.Root()) | ||||||
|  | 		fmt.Println("#####################################") | ||||||
|  | 	*/ | ||||||
| 	for key, value := range self.storage { | 	for key, value := range self.storage { | ||||||
| 		if value.BigInt().Cmp(ethutil.Big0) == 0 { | 		if value.Len() == 0 { // value.BigInt().Cmp(ethutil.Big0) == 0 { | ||||||
|  | 			//data := self.getStorage([]byte(key)) | ||||||
|  | 			//fmt.Printf("deleting %x %x 0x%x\n", self.Address(), []byte(key), data) | ||||||
| 			self.state.trie.Delete(string(key)) | 			self.state.trie.Delete(string(key)) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| @@ -163,6 +176,14 @@ func (self *StateObject) Sync() { | |||||||
|  |  | ||||||
| 		self.state.trie = t2 | 		self.state.trie = t2 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 		fmt.Println("############# AFTER ################") | ||||||
|  | 		self.state.EachStorage(func(key string, value *ethutil.Value) { | ||||||
|  | 			fmt.Printf("%x %x %x\n", self.Address(), []byte(key), value.Bytes()) | ||||||
|  | 		}) | ||||||
|  | 	*/ | ||||||
|  | 	//fmt.Printf("%x @:%x\n", self.Address(), self.state.Root()) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { | func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { | ||||||
|   | |||||||
| @@ -195,7 +195,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) { | |||||||
| 			val := closure.GetStorage(x) | 			val := closure.GetStorage(x) | ||||||
| 			if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 { | 			if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 { | ||||||
| 				mult = ethutil.Big2 | 				mult = ethutil.Big2 | ||||||
| 			} else if !val.IsEmpty() && len(y.Bytes()) == 0 { | 			} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 { | ||||||
| 				mult = ethutil.Big0 | 				mult = ethutil.Big0 | ||||||
| 			} else { | 			} else { | ||||||
| 				mult = ethutil.Big1 | 				mult = ethutil.Big1 | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/ethereum/eth-go/ethcrypto" | 	"github.com/ethereum/eth-go/ethcrypto" | ||||||
| 	"github.com/ethereum/eth-go/ethutil" | 	"github.com/ethereum/eth-go/ethutil" | ||||||
| 	"reflect" | 	_ "reflect" | ||||||
| 	"sync" | 	"sync" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -326,7 +326,8 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter | |||||||
|  |  | ||||||
| 	// New node | 	// New node | ||||||
| 	n := ethutil.NewValue(node) | 	n := ethutil.NewValue(node) | ||||||
| 	if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { | 	if node == nil || n.Len() == 0 { | ||||||
|  | 		//if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { | ||||||
| 		newNode := []interface{}{CompactEncode(key), value} | 		newNode := []interface{}{CompactEncode(key), value} | ||||||
|  |  | ||||||
| 		return t.Put(newNode) | 		return t.Put(newNode) | ||||||
| @@ -393,13 +394,17 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter | |||||||
|  |  | ||||||
| func (t *Trie) deleteState(node interface{}, key []int) interface{} { | func (t *Trie) deleteState(node interface{}, key []int) interface{} { | ||||||
| 	if len(key) == 0 { | 	if len(key) == 0 { | ||||||
|  | 		println("<empty ret>") | ||||||
| 		return "" | 		return "" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// New node | 	// New node | ||||||
| 	n := ethutil.NewValue(node) | 	n := ethutil.NewValue(node) | ||||||
| 	if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { | 	//if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { | ||||||
|  | 	if node == nil || n.Len() == 0 { | ||||||
| 		//return nil | 		//return nil | ||||||
|  | 		//fmt.Printf("<empty ret> %x %d\n", n, len(n.Bytes())) | ||||||
|  |  | ||||||
| 		return "" | 		return "" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -410,17 +415,19 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} { | |||||||
| 		k := CompactDecode(currentNode.Get(0).Str()) | 		k := CompactDecode(currentNode.Get(0).Str()) | ||||||
| 		v := currentNode.Get(1).Raw() | 		v := currentNode.Get(1).Raw() | ||||||
|  |  | ||||||
| 		matchingLength := MatchingNibbleLength(key, k) |  | ||||||
|  |  | ||||||
| 		// Matching key pair (ie. there's already an object with this key) | 		// Matching key pair (ie. there's already an object with this key) | ||||||
| 		if CompareIntSlice(k, key) { | 		if CompareIntSlice(k, key) { | ||||||
|  | 			//fmt.Printf("<delete ret> %x\n", v) | ||||||
|  |  | ||||||
| 			return "" | 			return "" | ||||||
| 		} else if CompareIntSlice(key[:matchingLength], k) { | 		} else if CompareIntSlice(key[:len(k)], k) { | ||||||
| 			hash := t.deleteState(v, key[len(k):]) | 			hash := t.deleteState(v, key[len(k):]) | ||||||
| 			child := t.getNode(hash) | 			child := t.getNode(hash) | ||||||
| 			if child.IsNil() { | 			/* | ||||||
| 				return node | 				if child.IsNil() { | ||||||
| 			} | 					return node | ||||||
|  | 				} | ||||||
|  | 			*/ | ||||||
|  |  | ||||||
| 			var newNode []interface{} | 			var newNode []interface{} | ||||||
| 			if child.Len() == 2 { | 			if child.Len() == 2 { | ||||||
| @@ -430,6 +437,8 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} { | |||||||
| 				newNode = []interface{}{currentNode.Get(0).Str(), hash} | 				newNode = []interface{}{currentNode.Get(0).Str(), hash} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			//fmt.Printf("%x\n", newNode) | ||||||
|  |  | ||||||
| 			return t.Put(newNode) | 			return t.Put(newNode) | ||||||
| 		} else { | 		} else { | ||||||
| 			return node | 			return node | ||||||
| @@ -472,10 +481,11 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} { | |||||||
| 			newNode = n | 			newNode = n | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		//fmt.Printf("%x\n", newNode) | ||||||
| 		return t.Put(newNode) | 		return t.Put(newNode) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return "" | 	panic("unexpected return") | ||||||
| } | } | ||||||
|  |  | ||||||
| type TrieIterator struct { | type TrieIterator struct { | ||||||
|   | |||||||
| @@ -1,17 +1,17 @@ | |||||||
| package ethtrie | package ethtrie | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	_ "bytes" | ||||||
| 	"encoding/hex" | 	_ "encoding/hex" | ||||||
| 	"encoding/json" | 	_ "encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/ethereum/eth-go/ethutil" | 	"github.com/ethereum/eth-go/ethutil" | ||||||
| 	"io/ioutil" | 	_ "io/ioutil" | ||||||
| 	"math/rand" | 	_ "math/rand" | ||||||
| 	"net/http" | 	_ "net/http" | ||||||
| 	"reflect" | 	_ "reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	_ "time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ" | const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ" | ||||||
| @@ -43,6 +43,7 @@ func New() (*MemDatabase, *Trie) { | |||||||
| 	return db, NewTrie(db, "") | 	return db, NewTrie(db, "") | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
| func TestTrieSync(t *testing.T) { | func TestTrieSync(t *testing.T) { | ||||||
| 	db, trie := New() | 	db, trie := New() | ||||||
|  |  | ||||||
| @@ -365,3 +366,55 @@ func TestDelete(t *testing.T) { | |||||||
|  |  | ||||||
| 	fmt.Printf("o: %x\nc: %x\n", a, b) | 	fmt.Printf("o: %x\nc: %x\n", a, b) | ||||||
| } | } | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | func TestRndCase(t *testing.T) { | ||||||
|  | 	_, trie := New() | ||||||
|  |  | ||||||
|  | 	data := []struct{ k, v string }{ | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000001", "a07573657264617461000000000000000000000000000000000000000000000000"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000003", "8453bb5b31"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000004", "850218711a00"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000005", "9462d7705bd0b3ecbc51a8026a25597cb28a650c79"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000010", "947e70f9460402290a3e487dae01f610a1a8218fda"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000111", "01"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000112", "a053656e6174650000000000000000000000000000000000000000000000000000"}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000113", "a053656e6174650000000000000000000000000000000000000000000000000000"}, | ||||||
|  | 		{"53656e6174650000000000000000000000000000000000000000000000000000", "94977e3f62f5e1ed7953697430303a3cfa2b5b736e"}, | ||||||
|  | 	} | ||||||
|  | 	for _, e := range data { | ||||||
|  | 		trie.Update(string(ethutil.Hex2Bytes(e.k)), string(ethutil.Hex2Bytes(e.v))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Printf("root after update %x\n", trie.Root) | ||||||
|  | 	trie.NewIterator().Each(func(k string, v *ethutil.Value) { | ||||||
|  | 		fmt.Printf("%x %x\n", k, v.Bytes()) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	data = []struct{ k, v string }{ | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000112", ""}, | ||||||
|  | 		{"436974697a656e73000000000000000000000000000000000000000000000001", ""}, | ||||||
|  | 		{"436f757274000000000000000000000000000000000000000000000000000002", ""}, | ||||||
|  | 		{"53656e6174650000000000000000000000000000000000000000000000000000", ""}, | ||||||
|  | 		{"436f757274000000000000000000000000000000000000000000000000000000", ""}, | ||||||
|  | 		{"53656e6174650000000000000000000000000000000000000000000000000001", ""}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000113", ""}, | ||||||
|  | 		{"436974697a656e73000000000000000000000000000000000000000000000000", ""}, | ||||||
|  | 		{"436974697a656e73000000000000000000000000000000000000000000000002", ""}, | ||||||
|  | 		{"436f757274000000000000000000000000000000000000000000000000000001", ""}, | ||||||
|  | 		{"0000000000000000000000000000000000000000000000000000000000000111", ""}, | ||||||
|  | 		{"53656e6174650000000000000000000000000000000000000000000000000002", ""}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, e := range data { | ||||||
|  | 		trie.Delete(string(ethutil.Hex2Bytes(e.k))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Printf("root after delete %x\n", trie.Root) | ||||||
|  |  | ||||||
|  | 	trie.NewIterator().Each(func(k string, v *ethutil.Value) { | ||||||
|  | 		fmt.Printf("%x %x\n", k, v.Bytes()) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	fmt.Printf("%x\n", trie.Get(string(ethutil.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")))) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -150,12 +150,16 @@ func LeftPadBytes(slice []byte, l int) []byte { | |||||||
| 	return padded | 	return padded | ||||||
| } | } | ||||||
|  |  | ||||||
| func Address(slice []byte) []byte { | func Address(slice []byte) (addr []byte) { | ||||||
| 	if len(slice) < 20 { | 	if len(slice) < 20 { | ||||||
| 		slice = LeftPadBytes(slice, 20) | 		addr = LeftPadBytes(slice, 20) | ||||||
| 	} else if len(slice) > 20 { | 	} else if len(slice) > 20 { | ||||||
| 		slice = slice[len(slice)-20:] | 		addr = slice[len(slice)-20:] | ||||||
|  | 	} else { | ||||||
|  | 		addr = slice | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return slice | 	addr = CopyBytes(addr) | ||||||
|  |  | ||||||
|  | 	return | ||||||
| } | } | ||||||
|   | |||||||
| @@ -40,13 +40,9 @@ func (val *Value) Len() int { | |||||||
| 	//return val.kind.Len() | 	//return val.kind.Len() | ||||||
| 	if data, ok := val.Val.([]interface{}); ok { | 	if data, ok := val.Val.([]interface{}); ok { | ||||||
| 		return len(data) | 		return len(data) | ||||||
| 	} else if data, ok := val.Val.([]byte); ok { |  | ||||||
| 		return len(data) |  | ||||||
| 	} else if data, ok := val.Val.(string); ok { |  | ||||||
| 		return len(data) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0 | 	return len(val.Bytes()) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (val *Value) Raw() interface{} { | func (val *Value) Raw() interface{} { | ||||||
| @@ -118,6 +114,8 @@ func (val *Value) Bytes() []byte { | |||||||
| 		return []byte{s} | 		return []byte{s} | ||||||
| 	} else if s, ok := val.Val.(string); ok { | 	} else if s, ok := val.Val.(string); ok { | ||||||
| 		return []byte(s) | 		return []byte(s) | ||||||
|  | 	} else if s, ok := val.Val.(*big.Int); ok { | ||||||
|  | 		return s.Bytes() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return []byte{} | 	return []byte{} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user