Trie fixes
This commit is contained in:
parent
14c4f06100
commit
ed3424ff75
@ -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() {
|
if child.IsNil() {
|
||||||
return node
|
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{}
|
||||||
|
Loading…
Reference in New Issue
Block a user