Simplifications
This commit is contained in:
parent
34288a91c9
commit
2be9984327
95
main.go
95
main.go
@ -1,7 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -30,25 +30,23 @@ var (
|
|||||||
CodeKey = types.NewKVStoreKey("code")
|
CodeKey = types.NewKVStoreKey("code")
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is what stored in the lookupDb
|
type CommitHashPreimage struct {
|
||||||
type LookupValue struct {
|
|
||||||
VersionId int64
|
VersionId int64
|
||||||
|
Prefix []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of eth_state.Database
|
// Implementation of eth_state.Database
|
||||||
type OurDatabase struct {
|
type OurDatabase struct {
|
||||||
stateStore store.CommitMultiStore // For the history of accounts <balance, nonce, storage root hash, code hash>
|
stateStore store.CommitMultiStore // For the history of accounts <balance, nonce, storage root hash, code hash>
|
||||||
// Also, for the history of contract data (effects of SSTORE instruction)
|
// Also, for the history of contract data (effects of SSTORE instruction)
|
||||||
lookupDb dbm.DB // Maping [trie_root_hash] => <version_id>.
|
accountsCache store.CacheKVStore
|
||||||
// This mapping exists so that we can implement OpenTrie and OpenStorageTrie functions
|
storageCache store.CacheKVStore
|
||||||
// of the state.Database interface
|
|
||||||
codeDb dbm.DB // Mapping [codeHash] -> <code>
|
codeDb dbm.DB // Mapping [codeHash] -> <code>
|
||||||
addrPreimageDb dbm.DB // Mapping [contract_address_hash] -> <contract_address>
|
|
||||||
cdc *amino.Codec // Amino codec to encode the values forthe lookupDb
|
cdc *amino.Codec // Amino codec to encode the values forthe lookupDb
|
||||||
tracing bool
|
tracing bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func OurNewDatabase(stateDb, lookupDb, addrPreimageDb, codeDb dbm.DB) (*OurDatabase, error) {
|
func OurNewDatabase(stateDb, codeDb dbm.DB) (*OurDatabase, error) {
|
||||||
od := &OurDatabase{}
|
od := &OurDatabase{}
|
||||||
od.stateStore = store.NewCommitMultiStore(stateDb)
|
od.stateStore = store.NewCommitMultiStore(stateDb)
|
||||||
od.stateStore.MountStoreWithDB(AccountsKey, types.StoreTypeIAVL, nil)
|
od.stateStore.MountStoreWithDB(AccountsKey, types.StoreTypeIAVL, nil)
|
||||||
@ -56,57 +54,45 @@ func OurNewDatabase(stateDb, lookupDb, addrPreimageDb, codeDb dbm.DB) (*OurDatab
|
|||||||
if err := od.stateStore.LoadLatestVersion(); err != nil {
|
if err := od.stateStore.LoadLatestVersion(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
od.lookupDb = lookupDb
|
|
||||||
od.addrPreimageDb = addrPreimageDb
|
|
||||||
od.codeDb = codeDb
|
od.codeDb = codeDb
|
||||||
od.cdc = amino.NewCodec()
|
od.cdc = amino.NewCodec()
|
||||||
return od, nil
|
return od, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// root is not interpreted as a hash, but as an encoding of version
|
||||||
func (od *OurDatabase) OpenTrie(root eth_common.Hash) (eth_state.Trie, error) {
|
func (od *OurDatabase) OpenTrie(root eth_common.Hash) (eth_state.Trie, error) {
|
||||||
// Look up version id to use
|
// Look up version id to use
|
||||||
hasData := root != (eth_common.Hash{})
|
hasData := root != (eth_common.Hash{})
|
||||||
|
var versionId int64
|
||||||
if hasData {
|
if hasData {
|
||||||
val := od.lookupDb.Get(root[:])
|
// First 8 bytes encode version
|
||||||
if val == nil {
|
versionId = int64(binary.BigEndian.Uint64(root[:8]))
|
||||||
return nil, fmt.Errorf("Could not find version with root hash %x", root[:])
|
|
||||||
}
|
|
||||||
var versionId int64
|
|
||||||
_, err := od.cdc.UnmarshalBinaryReader(bytes.NewBuffer(val), &versionId, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if od.tracing {
|
|
||||||
fmt.Printf("Loading version %d\n", versionId)
|
|
||||||
}
|
|
||||||
if err := od.stateStore.LoadVersion(versionId); err != nil {
|
if err := od.stateStore.LoadVersion(versionId); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st := od.stateStore.GetCommitKVStore(AccountsKey)
|
if od.accountsCache == nil {
|
||||||
return &OurTrie{od: od, st: st, prefix: nil, hasData: hasData}, nil
|
od.accountsCache = store.NewCacheKVStore(od.stateStore.GetCommitKVStore(AccountsKey))
|
||||||
|
}
|
||||||
|
return &OurTrie{od: od, versionId: versionId, st: od.accountsCache, prefix: nil, hasData: hasData}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (od *OurDatabase) OpenStorageTrie(addrHash, root eth_common.Hash) (eth_state.Trie, error) {
|
func (od *OurDatabase) OpenStorageTrie(addrHash, root eth_common.Hash) (eth_state.Trie, error) {
|
||||||
hasData := root != (eth_common.Hash{})
|
hasData := root != (eth_common.Hash{})
|
||||||
|
var versionId int64
|
||||||
if hasData {
|
if hasData {
|
||||||
val := od.lookupDb.Get(root[:])
|
// First 8 bytes encode version
|
||||||
if val == nil {
|
versionId = int64(binary.BigEndian.Uint64(root[:8]))
|
||||||
return nil, fmt.Errorf("Could not find version with root hash %x", root[:])
|
|
||||||
}
|
|
||||||
var versionId int64
|
|
||||||
_, err := od.cdc.UnmarshalBinaryReader(bytes.NewBuffer(val), &versionId, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// This might not be required,
|
// This might not be required,
|
||||||
// we just need to check that accounts and storage are consistent
|
// we just need to check that accounts and storage are consistent
|
||||||
if err := od.stateStore.LoadVersion(versionId); err != nil {
|
if err := od.stateStore.LoadVersion(versionId); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st := od.stateStore.GetCommitKVStore(StorageKey)
|
if od.storageCache == nil {
|
||||||
return &OurTrie{od:od, st: st, prefix: addrHash[:], hasData: hasData}, nil
|
od.storageCache = store.NewCacheKVStore(od.stateStore.GetCommitKVStore(StorageKey))
|
||||||
|
}
|
||||||
|
return &OurTrie{od:od, versionId: versionId, st: od.storageCache, prefix: addrHash[:], hasData: hasData}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (od *OurDatabase) CopyTrie(eth_state.Trie) eth_state.Trie {
|
func (od *OurDatabase) CopyTrie(eth_state.Trie) eth_state.Trie {
|
||||||
@ -130,8 +116,9 @@ func (od *OurDatabase) TrieDB() *eth_trie.Database {
|
|||||||
// Implementation of eth_state.Trie
|
// Implementation of eth_state.Trie
|
||||||
type OurTrie struct {
|
type OurTrie struct {
|
||||||
od *OurDatabase
|
od *OurDatabase
|
||||||
|
versionId int64
|
||||||
// This is essentially part of the KVStore for a specific prefix
|
// This is essentially part of the KVStore for a specific prefix
|
||||||
st store.CommitKVStore
|
st store.KVStore
|
||||||
prefix []byte
|
prefix []byte
|
||||||
hasData bool
|
hasData bool
|
||||||
}
|
}
|
||||||
@ -173,16 +160,18 @@ func (ot *OurTrie) Commit(onleaf eth_trie.LeafCallback) (eth_common.Hash, error)
|
|||||||
if !ot.hasData {
|
if !ot.hasData {
|
||||||
return eth_common.Hash{}, nil
|
return eth_common.Hash{}, nil
|
||||||
}
|
}
|
||||||
commitId := ot.st.Commit()
|
var commitHash eth_common.Hash
|
||||||
fmt.Printf("Committed version %d\n", commitId.Version)
|
// We assume here that the next committed version will be ot.versionId+1
|
||||||
var hash eth_common.Hash
|
binary.BigEndian.PutUint64(commitHash[:8], uint64(ot.versionId+1))
|
||||||
copy(hash[:], commitId.Hash)
|
if ot.od.accountsCache != nil {
|
||||||
b, err := ot.od.cdc.MarshalBinary(commitId.Version)
|
ot.od.accountsCache.Write()
|
||||||
if err != nil {
|
ot.od.accountsCache = nil
|
||||||
return hash, err
|
|
||||||
}
|
}
|
||||||
ot.od.lookupDb.Set(hash[:], b)
|
if ot.od.storageCache != nil {
|
||||||
return hash, nil
|
ot.od.storageCache.Write()
|
||||||
|
ot.od.storageCache = nil
|
||||||
|
}
|
||||||
|
return commitHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *OurTrie) Hash() eth_common.Hash {
|
func (ot *OurTrie) Hash() eth_common.Hash {
|
||||||
@ -204,10 +193,8 @@ func (ot *OurTrie) Prove(key []byte, fromLevel uint, proofDb eth_ethdb.Putter) e
|
|||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Instantiating state.Database\n")
|
fmt.Printf("Instantiating state.Database\n")
|
||||||
stateDb := dbm.NewDB("state" /* name */, dbm.MemDBBackend, "" /* dir */)
|
stateDb := dbm.NewDB("state" /* name */, dbm.MemDBBackend, "" /* dir */)
|
||||||
lookupDb := dbm.NewDB("lookup" /* name */, dbm.MemDBBackend, "" /* dir */)
|
|
||||||
addrPreimageDb := dbm.NewDB("addrPreimage" /* name */, dbm.MemDBBackend, "" /* dir */)
|
|
||||||
codeDb := dbm.NewDB("code" /* name */, dbm.MemDBBackend, "" /* dir */)
|
codeDb := dbm.NewDB("code" /* name */, dbm.MemDBBackend, "" /* dir */)
|
||||||
d, err := OurNewDatabase(stateDb, lookupDb, addrPreimageDb, codeDb)
|
d, err := OurNewDatabase(stateDb, codeDb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -234,6 +221,8 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
commitID := d.stateStore.Commit()
|
||||||
|
fmt.Printf("CommitID after genesis: %v\n", commitID)
|
||||||
fmt.Printf("Genesis state root hash: %x\n", genesis_root[:])
|
fmt.Printf("Genesis state root hash: %x\n", genesis_root[:])
|
||||||
// File with blockchain data exported from geth by using "geth expordb" command
|
// File with blockchain data exported from geth by using "geth expordb" command
|
||||||
input, err := os.Open("/Users/alexeyakhunov/mygit/blockchain")
|
input, err := os.Open("/Users/alexeyakhunov/mygit/blockchain")
|
||||||
@ -269,14 +258,17 @@ func main() {
|
|||||||
// Apply mining rewards to the statedb
|
// Apply mining rewards to the statedb
|
||||||
accumulateRewards(chainConfig, statedb, header, block.Uncles())
|
accumulateRewards(chainConfig, statedb, header, block.Uncles())
|
||||||
// Commit block
|
// Commit block
|
||||||
prev_root, err := statedb.Commit(chainConfig.IsEIP158(block.Number()) /* deleteEmptyObjects */)
|
prev_root, err = statedb.Commit(chainConfig.IsEIP158(block.Number()) /* deleteEmptyObjects */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("at block %d: %v", n, err))
|
panic(fmt.Errorf("at block %d: %v", n, err))
|
||||||
}
|
}
|
||||||
|
//fmt.Printf("State root after block %d: %x\n", block.NumberU64(), prev_root)
|
||||||
|
d.stateStore.Commit()
|
||||||
|
//fmt.Printf("CommitID after block %d: %v\n", block.NumberU64(), commitID)
|
||||||
switch block.NumberU64() {
|
switch block.NumberU64() {
|
||||||
case 1:
|
case 500:
|
||||||
root500 = prev_root
|
root500 = prev_root
|
||||||
case 502:
|
case 501:
|
||||||
root501 = prev_root
|
root501 = prev_root
|
||||||
}
|
}
|
||||||
n++
|
n++
|
||||||
@ -290,6 +282,7 @@ func main() {
|
|||||||
fmt.Printf("Balance of one of the genesis investors: %s\n", genesis_state.GetBalance(eth_common.HexToAddress("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0")))
|
fmt.Printf("Balance of one of the genesis investors: %s\n", genesis_state.GetBalance(eth_common.HexToAddress("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0")))
|
||||||
miner501 := eth_common.HexToAddress("0x35e8e5dC5FBd97c5b421A80B596C030a2Be2A04D") // Miner of the block 501
|
miner501 := eth_common.HexToAddress("0x35e8e5dC5FBd97c5b421A80B596C030a2Be2A04D") // Miner of the block 501
|
||||||
// Try to create a new statedb from root of the block 500
|
// Try to create a new statedb from root of the block 500
|
||||||
|
fmt.Printf("root500: %x\n", root500[:])
|
||||||
state500, err := eth_state.New(root500, d)
|
state500, err := eth_state.New(root500, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
Loading…
Reference in New Issue
Block a user