No longer store script directly in the state tree

This commit is contained in:
obscuren 2014-05-20 11:19:07 +02:00
parent a2fb265563
commit fd19142c0d
11 changed files with 70 additions and 52 deletions

View File

@ -122,7 +122,7 @@ func (block *Block) Transactions() []*Transaction {
}
func (block *Block) PayFee(addr []byte, fee *big.Int) bool {
contract := block.state.GetContract(addr)
contract := block.state.GetStateObject(addr)
// If we can't pay the fee return
if contract == nil || contract.Amount.Cmp(fee) < 0 /* amount < fee */ {
fmt.Println("Contract has insufficient funds", contract.Amount, fee)

View File

@ -260,7 +260,7 @@ func AddTestNetFunds(block *Block) {
"e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey
"1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran
//"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran
} {
//log.Println("2^200 Wei to", addr)
codedAddr := ethutil.FromHex(addr)

View File

@ -49,28 +49,6 @@ func (s *State) Purge() int {
return s.trie.NewIterator().Purge()
}
// XXX Deprecated
func (s *State) GetContract(addr []byte) *StateObject {
data := s.trie.Get(string(addr))
if data == "" {
return nil
}
// build contract
contract := NewStateObjectFromBytes(addr, []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
}
func (s *State) GetStateObject(addr []byte) *StateObject {
data := s.trie.Get(string(addr))
if data == "" {
@ -91,6 +69,21 @@ func (s *State) GetStateObject(addr []byte) *StateObject {
return stateObject
}
// Updates any given state object
func (s *State) UpdateStateObject(object *StateObject) {
addr := object.Address()
if object.state != nil {
s.states[string(addr)] = object.state
}
ethutil.Config.Db.Put(ethutil.Sha3Bin(object.Script()), object.Script())
s.trie.Update(string(addr), string(object.RlpEncode()))
s.manifest.AddObjectChange(object)
}
func (s *State) SetStateObject(stateObject *StateObject) {
s.states[string(stateObject.address)] = stateObject.state
@ -116,18 +109,6 @@ func (s *State) Copy() *State {
return NewState(s.trie.Copy())
}
// Updates any given state object
func (s *State) UpdateStateObject(object *StateObject) {
addr := object.Address()
if object.state != nil {
s.states[string(addr)] = object.state
}
s.trie.Update(string(addr), string(object.RlpEncode()))
s.manifest.AddObjectChange(object)
}
func (s *State) Put(key, object []byte) {
s.trie.Update(string(key), string(object))
}

View File

@ -87,7 +87,7 @@ func (sm *StateManager) BlockChain() *BlockChain {
func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject {
contract := MakeContract(tx, state)
if contract != nil {
state.states[string(tx.Hash()[12:])] = contract.state
state.states[string(tx.CreationAddress())] = contract.state
return contract
}
@ -117,7 +117,8 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra
}
} else {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
contract := state.GetContract(tx.Recipient)
contract := state.GetStateObject(tx.Recipient)
ethutil.Config.Log.Debugf("contract recip %x\n", tx.Recipient)
if err == nil && len(contract.Script()) > 0 {
sm.EvalScript(state, contract.Script(), contract, tx, block)
} else if err != nil {

View File

@ -11,6 +11,7 @@ type StateObject struct {
address []byte
// Shared attributes
Amount *big.Int
ScriptHash []byte
Nonce uint64
// Contract related attributes
state *State
@ -22,12 +23,10 @@ type StateObject struct {
func MakeContract(tx *Transaction, state *State) *StateObject {
// Create contract if there's no recipient
if tx.IsContract() {
// FIXME
addr := tx.Hash()[12:]
addr := tx.CreationAddress()
value := tx.Value
contract := NewContract(addr, value, []byte(""))
state.UpdateStateObject(contract)
contract := NewContract(addr, value, ZeroHash256)
contract.script = tx.Data
contract.initScript = tx.Init
@ -146,9 +145,10 @@ func (c *StateObject) RlpEncode() []byte {
if c.state != nil {
root = c.state.trie.Root
} else {
root = nil
root = ZeroHash256
}
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, c.script})
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, ethutil.Sha3Bin(c.script)})
}
func (c *StateObject) RlpDecode(data []byte) {
@ -157,7 +157,10 @@ func (c *StateObject) RlpDecode(data []byte) {
c.Amount = decoder.Get(0).BigInt()
c.Nonce = decoder.Get(1).Uint()
c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
c.script = decoder.Get(3).Bytes()
c.ScriptHash = decoder.Get(3).Bytes()
c.script, _ = ethutil.Config.Db.Get(c.ScriptHash)
}
// Storage change object. Used by the manifest for notifying changes to

View File

@ -0,0 +1,25 @@
package ethchain
import (
"fmt"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
"testing"
)
func TestSync(t *testing.T) {
ethutil.ReadConfig("", ethutil.LogStd)
db, _ := ethdb.NewMemDatabase()
state := NewState(ethutil.NewTrie(db, ""))
contract := NewContract([]byte("aa"), ethutil.Big1, ZeroHash256)
contract.script = []byte{42}
state.UpdateStateObject(contract)
state.Sync()
object := state.GetStateObject([]byte("aa"))
fmt.Printf("%x\n", object.Script())
}

View File

@ -60,7 +60,7 @@ func (tx *Transaction) IsContract() bool {
}
func (tx *Transaction) CreationAddress() []byte {
return tx.Hash()[12:]
return ethutil.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:]
}
func (tx *Transaction) Signature(key []byte) []byte {

View File

@ -471,7 +471,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
args := mem.Get(inOffset.Int64(), inSize.Int64())
// Fetch the contract which will serve as the closure body
contract := vm.state.GetContract(addr.Bytes())
contract := vm.state.GetStateObject(addr.Bytes())
if contract != nil {
// Prepay for the gas

View File

@ -45,7 +45,7 @@ func (lib *PEthereum) GetKey() *PKey {
}
func (lib *PEthereum) GetStateObject(address string) *PStateObject {
stateObject := lib.stateManager.CurrentState().GetContract(ethutil.FromHex(address))
stateObject := lib.stateManager.CurrentState().GetStateObject(ethutil.FromHex(address))
if stateObject != nil {
return NewPStateObject(stateObject)
}
@ -160,7 +160,6 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in
}
acc := lib.stateManager.TransState().GetStateObject(keyPair.Address())
//acc := lib.stateManager.GetAddrState(keyPair.Address())
tx.Nonce = acc.Nonce
acc.Nonce += 1
lib.stateManager.TransState().SetStateObject(acc)

View File

@ -2,6 +2,7 @@ package ethpub
import (
"encoding/hex"
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
)
@ -112,6 +113,14 @@ func (c *PStateObject) IsContract() bool {
return false
}
func (c *PStateObject) Script() string {
if c.object != nil {
return ethutil.Hex(c.object.Script())
}
return ""
}
type PStorageState struct {
StateAddress string
Address string

View File

@ -18,7 +18,7 @@ const (
// The size of the output buffer for writing messages
outputBufferSize = 50
// Current protocol version
ProtocolVersion = 8
ProtocolVersion = 9
)
type DiscReason byte