Commit b2500474 authored by George Hotz's avatar George Hotz

getting close on a block transition

parent 69b6305f
\ No newline at end of file
...@@ -101,8 +101,8 @@ async function getBlock(blockNumber: Number) { ...@@ -101,8 +101,8 @@ async function getBlock(blockNumber: Number) {
async function main() { async function main() {
/*await getBlock(13247501) /*await getBlock(13247501)
await getBlock(13247502)*/ await getBlock(13247502)*/
await getBlock(13284053) await getBlock(13284491)
await getBlock(13284054) await getBlock(13284492)
} }
main().then(() => process.exit(0)) main().then(() => process.exit(0))
...@@ -29,3 +29,9 @@ type Account struct { ...@@ -29,3 +29,9 @@ type Account struct {
The oracle ensures a correct output given the input, these are the high level methods The oracle ensures a correct output given the input, these are the high level methods
GetUnproved...need to be written also GetUnproved...need to be written also
# diving in more
core/state/database.go
...@@ -248,7 +248,8 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has ...@@ -248,7 +248,8 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
meter = &s.db.StorageReads meter = &s.db.StorageReads
} }
oracle.PrefetchAddress(db.BlockNumber, s.address, key) oracle.PrefetchStorage(db.BlockNumber, s.address, key)
fmt.Println("get", s.address, key)
if enc, err = s.getTrie(db).TryGet(key.Bytes()); err != nil { if enc, err = s.getTrie(db).TryGet(key.Bytes()); err != nil {
s.setError(err) s.setError(err)
return common.Hash{} return common.Hash{}
...@@ -354,10 +355,13 @@ func (s *stateObject) updateTrie(db Database) Trie { ...@@ -354,10 +355,13 @@ func (s *stateObject) updateTrie(db Database) Trie {
s.originStorage[key] = value s.originStorage[key] = value
var v []byte var v []byte
oracle.PrefetchAddress(db.BlockNumber, s.address, key) oracle.PrefetchStorage(db.BlockNumber, s.address, key)
//oracle.PrefetchStorage(big.NewInt(db.BlockNumber.Int64()+1), s.address, key)
if (value == common.Hash{}) { if (value == common.Hash{}) {
//s.setError(tr.TryDelete(key[:])) fmt.Println("delete", s.address, key)
s.setError(tr.TryDelete(key[:]))
} else { } else {
fmt.Println("update", s.address, key, value)
// Encoding []byte cannot fail, ok to ignore the error. // Encoding []byte cannot fail, ok to ignore the error.
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
s.setError(tr.TryUpdate(key[:], v)) s.setError(tr.TryUpdate(key[:], v))
......
...@@ -513,7 +513,7 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { ...@@ -513,7 +513,7 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now()) defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now())
} }
oracle.PrefetchAddress(s.db.BlockNumber, addr, common.Hash{}) oracle.PrefetchAddress(s.db.BlockNumber, addr)
enc, err := s.trie.TryGet(addr.Bytes()) enc, err := s.trie.TryGet(addr.Bytes())
if err != nil { if err != nil {
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %v", addr.Bytes(), err)) s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %v", addr.Bytes(), err))
...@@ -879,6 +879,20 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { ...@@ -879,6 +879,20 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
// Finalize any pending changes and merge everything into the tries // Finalize any pending changes and merge everything into the tries
s.IntermediateRoot(deleteEmptyObjects) s.IntermediateRoot(deleteEmptyObjects)
for addr := range s.stateObjectsDirty {
if obj := s.stateObjects[addr]; !obj.deleted {
fmt.Println("dirty state object", addr)
// Write any contract code associated with the state object
if obj.code != nil && obj.dirtyCode {
fmt.Println("write code", common.BytesToHash(obj.CodeHash()))
}
// Write any storage changes in the state object to its storage trie
if err := obj.CommitTrie(s.db); err != nil {
return common.Hash{}, err
}
}
}
// Commit objects to the trie, measuring the elapsed time // Commit objects to the trie, measuring the elapsed time
/*codeWriter := s.db.TrieDB().DiskDB().NewBatch() /*codeWriter := s.db.TrieDB().DiskDB().NewBatch()
for addr := range s.stateObjectsDirty { for addr := range s.stateObjectsDirty {
...@@ -943,7 +957,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { ...@@ -943,7 +957,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
} }
s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil
}*/ }*/
fmt.Println("Commit doesn't work!!!") //fmt.Println("Commit doesn't work!!!")
return root, err return root, err
} }
......
...@@ -14,10 +14,12 @@ import ( ...@@ -14,10 +14,12 @@ import (
) )
func main() { func main() {
//blockNumber := 13284469
blockNumber := 13284491
// read header // read header
var header types.Header var header types.Header
{ {
f, _ := os.Open("data/block_13284053") f, _ := os.Open(fmt.Sprintf("data/block_%d", blockNumber))
defer f.Close() defer f.Close()
rlpheader := rlp.NewStream(f, 0) rlpheader := rlp.NewStream(f, 0)
rlpheader.Decode(&header) rlpheader.Decode(&header)
...@@ -26,7 +28,7 @@ func main() { ...@@ -26,7 +28,7 @@ func main() {
// read header // read header
var newheader types.Header var newheader types.Header
{ {
f, _ := os.Open("data/block_13284054") f, _ := os.Open(fmt.Sprintf("data/block_%d", blockNumber+1))
defer f.Close() defer f.Close()
rlpheader := rlp.NewStream(f, 0) rlpheader := rlp.NewStream(f, 0)
rlpheader.Decode(&newheader) rlpheader.Decode(&newheader)
...@@ -42,7 +44,7 @@ func main() { ...@@ -42,7 +44,7 @@ func main() {
// read txs // read txs
var txs []*types.Transaction var txs []*types.Transaction
{ {
f, _ := os.Open("data/txs_13284054") f, _ := os.Open(fmt.Sprintf("data/txs_%d", blockNumber+1))
defer f.Close() defer f.Close()
rlpheader := rlp.NewStream(f, 0) rlpheader := rlp.NewStream(f, 0)
rlpheader.Decode(&txs) rlpheader.Decode(&txs)
......
...@@ -103,16 +103,31 @@ func Preimage(hash common.Hash) []byte { ...@@ -103,16 +103,31 @@ func Preimage(hash common.Hash) []byte {
return val return val
} }
func PrefetchAddress(blockNumber *big.Int, addr common.Address, skey common.Hash) { func PrefetchStorage(blockNumber *big.Int, addr common.Address, skey common.Hash) {
key := fmt.Sprintf("proof_%d_%s_%s", blockNumber, addr, skey) /*key := fmt.Sprintf("proof_%d_%s_%s", blockNumber, addr, skey)
fmt.Println("prefetch", key) if cached[key] {
return
}
cached[key] = true*/
ap := GetProofAccount(blockNumber, addr, skey, true)
//fmt.Println("PrefetchStorage", blockNumber, addr, skey, len(ap))
for _, s := range ap {
ret, _ := hex.DecodeString(s[2:])
hash := crypto.Keccak256Hash(ret)
//fmt.Println(" ", i, hash)
preimages[hash] = ret
}
}
func PrefetchAddress(blockNumber *big.Int, addr common.Address) {
key := fmt.Sprintf("proof_%d_%s", blockNumber, addr)
if cached[key] { if cached[key] {
//fmt.Println("hit", key)
return return
} }
cached[key] = true cached[key] = true
ap := GetProofAccount(blockNumber, addr, skey) ap := GetProofAccount(blockNumber, addr, common.Hash{}, false)
for _, s := range ap { for _, s := range ap {
ret, _ := hex.DecodeString(s[2:]) ret, _ := hex.DecodeString(s[2:])
hash := crypto.Keccak256Hash(ret) hash := crypto.Keccak256Hash(ret)
...@@ -120,8 +135,13 @@ func PrefetchAddress(blockNumber *big.Int, addr common.Address, skey common.Hash ...@@ -120,8 +135,13 @@ func PrefetchAddress(blockNumber *big.Int, addr common.Address, skey common.Hash
} }
} }
func GetProofAccount(blockNumber *big.Int, addr common.Address, skey common.Hash) []string { func GetProofAccount(blockNumber *big.Int, addr common.Address, skey common.Hash, storage bool) []string {
key := fmt.Sprintf("proof_%d_%s_%s", blockNumber, addr, skey) var key string
if storage {
key = fmt.Sprintf("proof_%d_%s_%s", blockNumber, addr, skey)
} else {
key = fmt.Sprintf("proof_%d_%s", blockNumber, addr)
}
addrHash := crypto.Keccak256Hash(addr[:]) addrHash := crypto.Keccak256Hash(addr[:])
unhashMap[addrHash] = addr unhashMap[addrHash] = addr
...@@ -138,10 +158,14 @@ func GetProofAccount(blockNumber *big.Int, addr common.Address, skey common.Hash ...@@ -138,10 +158,14 @@ func GetProofAccount(blockNumber *big.Int, addr common.Address, skey common.Hash
jr := jsonresp{} jr := jsonresp{}
json.NewDecoder(resp.Body).Decode(&jr) json.NewDecoder(resp.Body).Decode(&jr)
arr := jr.Result.AccountProof if storage {
arr = append(arr, jr.Result.StorageProof[0].Proof...) arr := jr.Result.StorageProof[0].Proof
cacheWrite(key, []byte(strings.Join(arr, "\n")))
} else {
arr := jr.Result.AccountProof
cacheWrite(key, []byte(strings.Join(arr, "\n")))
}
cacheWrite(key, []byte(strings.Join(arr, "\n")))
} }
return strings.Split(string(cacheRead(key)), "\n") return strings.Split(string(cacheRead(key)), "\n")
} }
......
...@@ -63,9 +63,9 @@ func (db *Database) preimage(hash common.Hash) []byte { ...@@ -63,9 +63,9 @@ func (db *Database) preimage(hash common.Hash) []byte {
func NewDatabase(header types.Header) Database { func NewDatabase(header types.Header) Database {
triedb := Database{BlockNumber: header.Number, Root: header.Root} triedb := Database{BlockNumber: header.Number, Root: header.Root}
triedb.preimages = make(map[common.Hash][]byte) //triedb.preimages = make(map[common.Hash][]byte)
fmt.Println("init database") fmt.Println("init database")
oracle.PrefetchAddress(header.Number, common.Address{}, common.Hash{}) oracle.PrefetchAddress(header.Number, common.Address{})
//panic("preseed") //panic("preseed")
return triedb return triedb
...@@ -82,7 +82,7 @@ func (db *Database) Node(hash common.Hash) ([]byte, error) { ...@@ -82,7 +82,7 @@ func (db *Database) Node(hash common.Hash) ([]byte, error) {
// node retrieves a cached trie node from memory, or returns nil if none can be // node retrieves a cached trie node from memory, or returns nil if none can be
// found in the memory cache. // found in the memory cache.
func (db *Database) node(hash common.Hash) node { func (db *Database) node(hash common.Hash) node {
fmt.Println("node", hash) //fmt.Println("node", hash)
return mustDecodeNode(hash[:], oracle.Preimage(hash)) return mustDecodeNode(hash[:], oracle.Preimage(hash))
} }
...@@ -93,4 +93,5 @@ func (db *Database) node(hash common.Hash) node { ...@@ -93,4 +93,5 @@ func (db *Database) node(hash common.Hash) node {
func (db *Database) insert(hash common.Hash, size int, node node) { func (db *Database) insert(hash common.Hash, size int, node node) {
//panic("insert") //panic("insert")
//fmt.Println("insert", hash, size) //fmt.Println("insert", hash, size)
// can put things in the oracle here if we care
} }
...@@ -368,6 +368,7 @@ func (t *Trie) TryDelete(key []byte) error { ...@@ -368,6 +368,7 @@ func (t *Trie) TryDelete(key []byte) error {
func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) { func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
switch n := n.(type) { switch n := n.(type) {
case *shortNode: case *shortNode:
fmt.Println("delete shortNode", prefix, key, n.Key, n.Val)
matchlen := prefixLen(key, n.Key) matchlen := prefixLen(key, n.Key)
if matchlen < len(n.Key) { if matchlen < len(n.Key) {
return false, n, nil // don't replace n on mismatch return false, n, nil // don't replace n on mismatch
...@@ -397,6 +398,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) { ...@@ -397,6 +398,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
} }
case *fullNode: case *fullNode:
fmt.Println("delete fullNode", prefix, key)
dirty, nn, err := t.delete(n.Children[key[0]], append(prefix, key[0]), key[1:]) dirty, nn, err := t.delete(n.Children[key[0]], append(prefix, key[0]), key[1:])
if !dirty || err != nil { if !dirty || err != nil {
return false, n, err return false, n, err
...@@ -435,12 +437,15 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) { ...@@ -435,12 +437,15 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
} }
if pos >= 0 { if pos >= 0 {
if pos != 16 { if pos != 16 {
fmt.Println("delete fails here", pos, n.Children, prefix, n.Children[pos])
// If the remaining entry is a short node, it replaces // If the remaining entry is a short node, it replaces
// n and its key gets the missing nibble tacked to the // n and its key gets the missing nibble tacked to the
// front. This avoids creating an invalid // front. This avoids creating an invalid
// shortNode{..., shortNode{...}}. Since the entry // shortNode{..., shortNode{...}}. Since the entry
// might not be loaded yet, resolve it just for this // might not be loaded yet, resolve it just for this
// check. // check.
// remove this optimisticly? if it's not a shortNode, it doesn't do anything
cnode, err := t.resolve(n.Children[pos], prefix) cnode, err := t.resolve(n.Children[pos], prefix)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
...@@ -464,6 +469,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) { ...@@ -464,6 +469,7 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
return false, nil, nil return false, nil, nil
case hashNode: case hashNode:
fmt.Println("delete hashNode", prefix, key)
// We've hit a part of the trie that isn't loaded yet. Load // We've hit a part of the trie that isn't loaded yet. Load
// the node and delete from it. This leaves all child nodes on // the node and delete from it. This leaves all child nodes on
// the path to the value in the trie. // the path to the value in the trie.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment