laconicd/main.go

168 lines
4.7 KiB
Go
Raw Normal View History

2018-06-13 09:56:01 +00:00
package main
import (
"bytes"
2018-06-13 09:56:01 +00:00
"fmt"
eth_common "github.com/ethereum/go-ethereum/common"
eth_state "github.com/ethereum/go-ethereum/core/state"
eth_ethdb "github.com/ethereum/go-ethereum/ethdb"
eth_trie "github.com/ethereum/go-ethereum/trie"
dbm "github.com/tendermint/tmlibs/db"
"github.com/tendermint/go-amino"
2018-06-13 14:29:22 +00:00
"github.com/cosmos/cosmos-sdk/store"
2018-06-15 10:05:12 +00:00
"github.com/cosmos/cosmos-sdk/types"
)
var (
// Key for the sub-store with Ethereum accounts
AccountsKey= types.NewKVStoreKey("account")
// Key for the sub-store with storage data of Ethereum contracts
StorageKey = types.NewKVStoreKey("storage")
2018-06-13 09:56:01 +00:00
)
// This is what stored in the lookupDb
type LookupValue struct {
VersionId int64
}
2018-06-13 09:56:01 +00:00
// Implementation of eth_state.Database
type OurDatabase struct {
2018-06-15 10:05:12 +00:00
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)
2018-06-15 21:32:35 +00:00
lookupDb dbm.DB // Maping [trie_root_hash] => <version_id>.
// This mapping exists so that we can implement OpenTrie and OpenStorageTrie functions
// of the state.Database interface
addrPreimageDb dbm.DB // Mapping [contract_address_hash] -> <contract_address>
cdc *amino.Codec // Amino codec to encode the values forthe lookupDb
2018-06-13 09:56:01 +00:00
}
2018-06-15 10:05:12 +00:00
func OurNewDatabase(stateDb, lookupDb dbm.DB) *OurDatabase {
od := &OurDatabase{}
od.stateStore = store.NewCommitMultiStore(stateDb)
od.stateStore.MountStoreWithDB(AccountsKey, types.StoreTypeIAVL, nil)
od.stateStore.MountStoreWithDB(StorageKey, types.StoreTypeIAVL, nil)
od.lookupDb = lookupDb
od.cdc = amino.NewCodec()
2018-06-15 10:05:12 +00:00
return od
2018-06-13 09:56:01 +00:00
}
func (od *OurDatabase) OpenTrie(root eth_common.Hash) (eth_state.Trie, error) {
// Look up version id to use
val := od.lookupDb.Get(root[:])
2018-06-15 21:32:35 +00:00
var versionId int64
_, err := od.cdc.UnmarshalBinaryReader(bytes.NewBuffer(val), &versionId, 0)
if err != nil {
return nil, err
}
2018-06-15 21:32:35 +00:00
od.stateStore.LoadVersion(versionId)
st := od.stateStore.GetCommitKVStore(AccountsKey)
2018-06-15 21:32:35 +00:00
return &OurTrie{od: od, st: st, prefix: nil}, nil
2018-06-13 09:56:01 +00:00
}
func (od *OurDatabase) OpenStorageTrie(addrHash, root eth_common.Hash) (eth_state.Trie, error) {
val := od.lookupDb.Get(root[:])
2018-06-15 21:32:35 +00:00
var versionId int64
_, err := od.cdc.UnmarshalBinaryReader(bytes.NewBuffer(val), &versionId, 0)
if err != nil {
return nil, err
}
2018-06-15 21:32:35 +00:00
od.stateStore.LoadVersion(versionId) // This might not be required,
// we just need to check that accounts and storage are consistent
st := od.stateStore.GetCommitKVStore(StorageKey)
2018-06-15 21:32:35 +00:00
return &OurTrie{od:od, st: st, prefix: addrHash[:]}, nil
2018-06-13 09:56:01 +00:00
}
func (od *OurDatabase) CopyTrie(eth_state.Trie) eth_state.Trie {
return nil
}
func (od *OurDatabase) ContractCode(addrHash, codeHash eth_common.Hash) ([]byte, error) {
return nil, nil
}
func (od *OurDatabase) ContractCodeSize(addrHash, codeHash eth_common.Hash) (int, error) {
return 0, nil
}
func (od *OurDatabase) TrieDB() *eth_trie.Database {
return nil
}
// Implementation of eth_state.Trie
type OurTrie struct {
2018-06-15 21:32:35 +00:00
od *OurDatabase
2018-06-15 10:05:12 +00:00
// This is essentially part of the KVStore for a specific prefix
2018-06-15 20:51:55 +00:00
st store.CommitKVStore
2018-06-15 10:05:12 +00:00
prefix []byte
2018-06-13 09:56:01 +00:00
}
2018-06-15 20:51:55 +00:00
func (ot *OurTrie) makePrefix(key []byte) []byte {
kk := make([]byte, len(ot.prefix)+len(key))
copy(kk, ot.prefix)
copy(kk[len(ot.prefix):], key)
return kk
}
2018-06-13 09:56:01 +00:00
func (ot *OurTrie) TryGet(key []byte) ([]byte, error) {
2018-06-15 20:51:55 +00:00
if ot.prefix == nil {
return ot.st.Get(key), nil
}
return ot.st.Get(ot.makePrefix(key)), nil
2018-06-13 09:56:01 +00:00
}
func (ot *OurTrie) TryUpdate(key, value []byte) error {
2018-06-15 20:51:55 +00:00
if ot.prefix == nil {
ot.st.Set(key, value)
return nil
}
ot.st.Set(ot.makePrefix(key), value)
2018-06-13 09:56:01 +00:00
return nil
}
func (ot *OurTrie) TryDelete(key []byte) error {
2018-06-15 20:51:55 +00:00
if ot.prefix == nil {
ot.st.Delete(key)
return nil
}
ot.st.Delete(ot.makePrefix(key))
2018-06-13 09:56:01 +00:00
return nil
}
func (ot *OurTrie) Commit(onleaf eth_trie.LeafCallback) (eth_common.Hash, error) {
2018-06-15 21:32:35 +00:00
commitId := ot.st.Commit()
var hash eth_common.Hash
copy(hash[:], commitId.Hash)
b, err := ot.od.cdc.MarshalBinary(commitId.Version)
if err != nil {
return hash, err
}
ot.od.lookupDb.Set(hash[:], b)
return hash, nil
2018-06-13 09:56:01 +00:00
}
func (ot *OurTrie) Hash() eth_common.Hash {
return eth_common.Hash{}
}
func (ot *OurTrie) NodeIterator(startKey []byte) eth_trie.NodeIterator {
return nil
}
func (ot *OurTrie) GetKey([]byte) []byte {
return nil
}
func (ot *OurTrie) Prove(key []byte, fromLevel uint, proofDb eth_ethdb.Putter) error {
return nil
}
func main() {
fmt.Printf("Instantiating state.Database\n")
2018-06-15 10:05:12 +00:00
stateDb := dbm.NewDB("state" /* name */, dbm.MemDBBackend, "" /* dir */)
lookupDb := dbm.NewDB("lookup" /* name */, dbm.MemDBBackend, "" /* dir */)
2018-06-13 09:56:01 +00:00
var d eth_state.Database
2018-06-15 10:05:12 +00:00
d = OurNewDatabase(stateDb, lookupDb)
2018-06-13 09:56:01 +00:00
d.OpenTrie(eth_common.Hash{})
}