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
+1 -1
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)
+1 -1
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)
+15 -34
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))
}
+3 -2
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 {
+12 -9
View File
@@ -10,8 +10,9 @@ type StateObject struct {
// Address of the object
address []byte
// Shared attributes
Amount *big.Int
Nonce uint64
Amount *big.Int
ScriptHash []byte
Nonce uint64
// Contract related attributes
state *State
script []byte
@@ -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
+25
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())
}
+1 -1
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 {
+1 -1
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