good morning!!!!

Skip to content
Snippets Groups Projects
Commit bfed1c7c authored by Jeffrey Wilcke's avatar Jeffrey Wilcke
Browse files

Trie's are no longer referenced directly but through State instead

parent d2bc57cd
No related branches found
No related tags found
No related merge requests found
...@@ -126,54 +126,6 @@ func (block *Block) Transactions() []*Transaction { ...@@ -126,54 +126,6 @@ func (block *Block) Transactions() []*Transaction {
return block.transactions return block.transactions
} }
/*
func (block *Block) GetContract(addr []byte) *Contract {
data := block.state.Get(string(addr))
if data == "" {
return nil
}
value := ethutil.NewValueFromBytes([]byte(data))
if value.Len() == 2 {
return nil
}
contract := &Contract{}
contract.RlpDecode([]byte(data))
cachedState := block.contractStates[string(addr)]
if cachedState != nil {
contract.state = cachedState
} else {
block.contractStates[string(addr)] = contract.state
}
return contract
}
func (block *Block) UpdateContract(addr []byte, contract *Contract) {
// Make sure the state is synced
//contract.State().Sync()
block.state.trie.Update(string(addr), string(contract.RlpEncode()))
}
func (block *Block) GetAddr(addr []byte) *Address {
var address *Address
data := block.state.trie.Get(string(addr))
if data == "" {
address = NewAddress(big.NewInt(0))
} else {
address = NewAddressFromData([]byte(data))
}
return address
}
func (block *Block) UpdateAddr(addr []byte, address *Address) {
block.state.trie.Update(string(addr), string(address.RlpEncode()))
}
*/
func (block *Block) PayFee(addr []byte, fee *big.Int) bool { func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
contract := block.state.GetContract(addr) contract := block.state.GetContract(addr)
// If we can't pay the fee return // If we can't pay the fee return
...@@ -210,23 +162,10 @@ func (block *Block) BlockInfo() BlockInfo { ...@@ -210,23 +162,10 @@ func (block *Block) BlockInfo() BlockInfo {
// Sync the block's state and contract respectively // Sync the block's state and contract respectively
func (block *Block) Sync() { func (block *Block) Sync() {
/* block.state.Sync()
// Sync all contracts currently in cache
for _, val := range block.contractStates {
val.Sync()
}
*/
// Sync the block state itself
block.state.trie.Sync()
} }
func (block *Block) Undo() { func (block *Block) Undo() {
/*
// Sync all contracts currently in cache
for _, val := range block.contractStates {
val.Undo()
}
*/
// Sync the block state itself // Sync the block state itself
block.state.Reset() block.state.Reset()
} }
...@@ -234,7 +173,7 @@ func (block *Block) Undo() { ...@@ -234,7 +173,7 @@ func (block *Block) Undo() {
func (block *Block) MakeContract(tx *Transaction) { func (block *Block) MakeContract(tx *Transaction) {
contract := MakeContract(tx, block.state) contract := MakeContract(tx, block.state)
if contract != nil { if contract != nil {
block.contractStates[string(tx.Hash()[12:])] = contract.state block.state.states[string(tx.Hash()[12:])] = contract.state
} }
} }
......
...@@ -8,18 +8,19 @@ import ( ...@@ -8,18 +8,19 @@ import (
type Contract struct { type Contract struct {
Amount *big.Int Amount *big.Int
Nonce uint64 Nonce uint64
state *ethutil.Trie //state *ethutil.Trie
state *State
} }
func NewContract(Amount *big.Int, root []byte) *Contract { func NewContract(Amount *big.Int, root []byte) *Contract {
contract := &Contract{Amount: Amount, Nonce: 0} contract := &Contract{Amount: Amount, Nonce: 0}
contract.state = ethutil.NewTrie(ethutil.Config.Db, string(root)) contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, string(root)))
return contract return contract
} }
func (c *Contract) RlpEncode() []byte { func (c *Contract) RlpEncode() []byte {
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.Root}) return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root})
} }
func (c *Contract) RlpDecode(data []byte) { func (c *Contract) RlpDecode(data []byte) {
...@@ -27,18 +28,18 @@ func (c *Contract) RlpDecode(data []byte) { ...@@ -27,18 +28,18 @@ func (c *Contract) RlpDecode(data []byte) {
c.Amount = decoder.Get(0).BigInt() c.Amount = decoder.Get(0).BigInt()
c.Nonce = decoder.Get(1).Uint() c.Nonce = decoder.Get(1).Uint()
c.state = ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()) c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
} }
func (c *Contract) Addr(addr []byte) *ethutil.Value { func (c *Contract) Addr(addr []byte) *ethutil.Value {
return ethutil.NewValueFromBytes([]byte(c.state.Get(string(addr)))) return ethutil.NewValueFromBytes([]byte(c.state.trie.Get(string(addr))))
} }
func (c *Contract) SetAddr(addr []byte, value interface{}) { func (c *Contract) SetAddr(addr []byte, value interface{}) {
c.state.Update(string(addr), string(ethutil.NewValue(value).Encode())) c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
} }
func (c *Contract) State() *ethutil.Trie { func (c *Contract) State() *State {
return c.state return c.state
} }
...@@ -59,7 +60,7 @@ func MakeContract(tx *Transaction, state *State) *Contract { ...@@ -59,7 +60,7 @@ func MakeContract(tx *Transaction, state *State) *Contract {
for i, val := range tx.Data { for i, val := range tx.Data {
if len(val) > 0 { if len(val) > 0 {
bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256) bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256)
contract.state.Update(string(bytNum), string(ethutil.Encode(val))) contract.state.trie.Update(string(bytNum), string(ethutil.Encode(val)))
} }
} }
state.trie.Update(string(addr), string(contract.RlpEncode())) state.trie.Update(string(addr), string(contract.RlpEncode()))
......
...@@ -5,16 +5,46 @@ import ( ...@@ -5,16 +5,46 @@ import (
"math/big" "math/big"
) )
// States within the ethereum protocol are used to store anything
// within the merkle trie. States take care of caching and storing
// nested states. It's the general query interface to retrieve:
// * Contracts
// * Accounts
type State struct { type State struct {
// The trie for this structure
trie *ethutil.Trie trie *ethutil.Trie
// Nested states
states map[string]*State
} }
// Create a new state from a given trie
func NewState(trie *ethutil.Trie) *State { func NewState(trie *ethutil.Trie) *State {
return &State{trie: trie} return &State{trie: trie, states: make(map[string]*State)}
} }
// Resets the trie and all siblings
func (s *State) Reset() { func (s *State) Reset() {
s.trie.Undo() s.trie.Undo()
// Reset all nested states
for _, state := range s.states {
state.Reset()
}
}
// Syncs the trie and all siblings
func (s *State) Sync() {
s.trie.Sync()
// Sync all nested states
for _, state := range s.states {
state.Sync()
}
}
// Purges the current trie.
func (s *State) Purge() int {
return s.trie.NewIterator().Purge()
} }
func (s *State) GetContract(addr []byte) *Contract { func (s *State) GetContract(addr []byte) *Contract {
...@@ -23,9 +53,28 @@ func (s *State) GetContract(addr []byte) *Contract { ...@@ -23,9 +53,28 @@ func (s *State) GetContract(addr []byte) *Contract {
return nil return nil
} }
// Whet get contract is called the retrieved value might
// be an account. The StateManager uses this to check
// to see if the address a tx was sent to is a contract
// or an account
value := ethutil.NewValueFromBytes([]byte(data))
if value.Len() == 2 {
return nil
}
// build contract
contract := &Contract{} contract := &Contract{}
contract.RlpDecode([]byte(data)) contract.RlpDecode([]byte(data))
// Check if there's a cached state for this contract
cachedState := s.states[string(addr)]
if cachedState != nil {
contract.state = cachedState
} else {
// If it isn't cached, cache the state
s.states[string(addr)] = contract.state
}
return contract return contract
} }
......
...@@ -330,7 +330,7 @@ out: ...@@ -330,7 +330,7 @@ out:
// Load the value in storage and push it on the stack // Load the value in storage and push it on the stack
x := vm.stack.Pop() x := vm.stack.Pop()
// decode the object as a big integer // decode the object as a big integer
decoder := ethutil.NewValueFromBytes([]byte(contract.State().Get(x.String()))) decoder := contract.Addr(x.Bytes())
if !decoder.IsNil() { if !decoder.IsNil() {
vm.stack.Push(decoder.BigInt()) vm.stack.Push(decoder.BigInt())
} else { } else {
...@@ -375,7 +375,7 @@ out: ...@@ -375,7 +375,7 @@ out:
case oSUICIDE: case oSUICIDE:
recAddr := vm.stack.Pop().Bytes() recAddr := vm.stack.Pop().Bytes()
// Purge all memory // Purge all memory
deletedMemory := contract.state.NewIterator().Purge() deletedMemory := contract.state.Purge()
// Add refunds to the pop'ed address // Add refunds to the pop'ed address
refund := new(big.Int).Mul(StoreFee, big.NewInt(int64(deletedMemory))) refund := new(big.Int).Mul(StoreFee, big.NewInt(int64(deletedMemory)))
account := state.GetAccount(recAddr) account := state.GetAccount(recAddr)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment