Upped version number

This commit is contained in:
obscuren 2014-04-27 16:50:44 +02:00
parent 05d2d8f27d
commit 16e52327a4
9 changed files with 129 additions and 12 deletions

View File

@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof Ethereum is currently in its testing phase. The current state is "Proof
of Concept 3.5". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). of Concept 5.0". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
Ethereum Go is split up in several sub packages Please refer to each Ethereum Go is split up in several sub packages Please refer to each
individual package for more information. individual package for more information.

View File

@ -8,21 +8,24 @@ import (
) )
type Callee interface { type Callee interface {
ReturnGas(*big.Int, *big.Int, *State)
Address() []byte
} }
type Reference interface { type Reference interface {
Callee Callee
ethutil.RlpEncodable }
type ClosureRef interface {
ReturnGas(*big.Int, *big.Int, *State)
Address() []byte
GetMem(*big.Int) *ethutil.Value GetMem(*big.Int) *ethutil.Value
SetMem(*big.Int, *ethutil.Value) SetMem(*big.Int, *ethutil.Value)
N() *big.Int
} }
// Basic inline closure object which implement the 'closure' interface // Basic inline closure object which implement the 'closure' interface
type Closure struct { type Closure struct {
callee Callee callee ClosureRef
object Reference object ClosureRef
Script []byte Script []byte
State *State State *State
@ -34,7 +37,7 @@ type Closure struct {
} }
// Create a new closure for the given data items // Create a new closure for the given data items
func NewClosure(callee Callee, object Reference, script []byte, state *State, gas, price, val *big.Int) *Closure { func NewClosure(callee, object ClosureRef, script []byte, state *State, gas, price, val *big.Int) *Closure {
c := &Closure{callee: callee, object: object, Script: script, State: state, Args: nil} c := &Closure{callee: callee, object: object, Script: script, State: state, Args: nil}
// In most cases gas, price and value are pointers to transaction objects // In most cases gas, price and value are pointers to transaction objects
@ -105,10 +108,14 @@ func (c *Closure) ReturnGas(gas, price *big.Int, state *State) {
c.Gas.Add(c.Gas, gas) c.Gas.Add(c.Gas, gas)
} }
func (c *Closure) Object() Reference { func (c *Closure) Object() ClosureRef {
return c.object return c.object
} }
func (c *Closure) Callee() Callee { func (c *Closure) Callee() ClosureRef {
return c.callee return c.callee
} }
func (c *Closure) N() *big.Int {
return c.object.N()
}

View File

@ -67,6 +67,18 @@ func (st *Stack) Peekn() (*big.Int, *big.Int) {
func (st *Stack) Push(d *big.Int) { func (st *Stack) Push(d *big.Int) {
st.data = append(st.data, d) st.data = append(st.data, d)
} }
func (st *Stack) Get(amount *big.Int) []*big.Int {
// offset + size <= len(data)
length := big.NewInt(int64(len(st.data)))
if amount.Cmp(length) <= 0 {
start := new(big.Int).Sub(length, amount)
return st.data[start.Int64():length.Int64()]
}
return nil
}
func (st *Stack) Print() { func (st *Stack) Print() {
fmt.Println("### stack ###") fmt.Println("### stack ###")
if len(st.data) > 0 { if len(st.data) > 0 {

View File

@ -47,6 +47,7 @@ func (s *State) Purge() int {
return s.trie.NewIterator().Purge() return s.trie.NewIterator().Purge()
} }
// XXX Deprecated
func (s *State) GetContract(addr []byte) *StateObject { func (s *State) GetContract(addr []byte) *StateObject {
data := s.trie.Get(string(addr)) data := s.trie.Get(string(addr))
if data == "" { if data == "" {
@ -68,6 +69,32 @@ func (s *State) GetContract(addr []byte) *StateObject {
return contract return contract
} }
func (s *State) GetStateObject(addr []byte) *StateObject {
data := s.trie.Get(string(addr))
if data == "" {
return nil
}
stateObject := NewStateObjectFromBytes(addr, []byte(data))
// Check if there's a cached state for this contract
cachedStateObject := s.states[string(addr)]
if cachedStateObject != nil {
stateObject.state = cachedStateObject
} else {
// If it isn't cached, cache the state
s.states[string(addr)] = stateObject.state
}
return stateObject
}
func (s *State) SetStateObject(stateObject *StateObject) {
s.states[string(stateObject.address)] = stateObject.state
s.UpdateStateObject(stateObject)
}
func (s *State) GetAccount(addr []byte) (account *StateObject) { func (s *State) GetAccount(addr []byte) (account *StateObject) {
data := s.trie.Get(string(addr)) data := s.trie.Get(string(addr))
if data == "" { if data == "" {
@ -97,6 +124,7 @@ const (
UnknownTy UnknownTy
) )
/*
// Returns the object stored at key and the type stored at key // Returns the object stored at key and the type stored at key
// Returns nil if nothing is stored // Returns nil if nothing is stored
func (s *State) GetStateObject(key []byte) (*ethutil.Value, ObjType) { func (s *State) GetStateObject(key []byte) (*ethutil.Value, ObjType) {
@ -124,6 +152,7 @@ func (s *State) GetStateObject(key []byte) (*ethutil.Value, ObjType) {
return val, typ return val, typ
} }
*/
// Updates any given state object // Updates any given state object
func (s *State) UpdateStateObject(object *StateObject) { func (s *State) UpdateStateObject(object *StateObject) {

View File

@ -65,6 +65,10 @@ func (c *StateObject) State() *State {
return c.state return c.state
} }
func (c *StateObject) N() *big.Int {
return big.NewInt(int64(c.Nonce))
}
func (c *StateObject) Addr(addr []byte) *ethutil.Value { func (c *StateObject) Addr(addr []byte) *ethutil.Value {
return ethutil.NewValueFromBytes([]byte(c.state.trie.Get(string(addr)))) return ethutil.NewValueFromBytes([]byte(c.state.trie.Get(string(addr))))
} }

View File

@ -20,6 +20,17 @@ var (
GasMemory = big.NewInt(1) GasMemory = big.NewInt(1)
) )
func CalculateTxGas(initSize, scriptSize *big.Int) *big.Int {
totalGas := new(big.Int)
totalGas.Add(totalGas, GasCreate)
txTotalBytes := new(big.Int).Add(initSize, scriptSize)
txTotalBytes.Div(txTotalBytes, ethutil.Big32)
totalGas.Add(totalGas, new(big.Int).Mul(txTotalBytes, GasSStore))
return totalGas
}
type Vm struct { type Vm struct {
txPool *TxPool txPool *TxPool
// Stack for processing contracts // Stack for processing contracts
@ -125,7 +136,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case oBALANCE: case oBALANCE:
useGas(GasBalance) useGas(GasBalance)
case oCREATE: case oCREATE:
useGas(GasCreate) require(3)
args := stack.Get(big.NewInt(3))
initSize := new(big.Int).Add(args[1], args[0])
useGas(CalculateTxGas(initSize, ethutil.Big0))
case oCALL: case oCALL:
useGas(GasCall) useGas(GasCall)
case oMLOAD, oMSIZE, oMSTORE8, oMSTORE: case oMLOAD, oMSIZE, oMSTORE8, oMSTORE:
@ -413,6 +429,39 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack.Push(big.NewInt(int64(mem.Len()))) stack.Push(big.NewInt(int64(mem.Len())))
// 0x60 range // 0x60 range
case oCREATE: case oCREATE:
require(3)
value := stack.Pop()
size, offset := stack.Popn()
// Generate a new address
addr := ethutil.CreateAddress(closure.callee.Address(), closure.callee.N())
// Create a new contract
contract := NewContract(addr, value, []byte(""))
// Set the init script
contract.initScript = mem.Get(offset.Int64(), size.Int64())
// Transfer all remaining gas to the new
// contract so it may run the init script
gas := new(big.Int).Set(closure.Gas)
closure.Gas.Sub(closure.Gas, gas)
// Create the closure
closure := NewClosure(closure.callee,
closure.Object(),
contract.initScript,
vm.state,
gas,
closure.Price,
value)
// Call the closure and set the return value as
// main script.
closure.Script, err = closure.Call(vm, nil, hook)
if err != nil {
stack.Push(ethutil.BigFalse)
} else {
stack.Push(ethutil.BigD(addr))
vm.state.SetStateObject(contract)
}
case oCALL: case oCALL:
require(7) require(7)
// Closure addr // Closure addr
@ -438,7 +487,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Prepay for the gas // Prepay for the gas
// If gas is set to 0 use all remaining gas for the next call // If gas is set to 0 use all remaining gas for the next call
if gas.Cmp(big.NewInt(0)) == 0 { if gas.Cmp(big.NewInt(0)) == 0 {
gas = closure.Gas // Copy
gas = new(big.Int).Set(closure.Gas)
} }
closure.Gas.Sub(closure.Gas, gas) closure.Gas.Sub(closure.Gas, gas)
// Create a new callable closure // Create a new callable closure

View File

@ -50,3 +50,11 @@ func BigCopy(src *big.Int) (ret *big.Int) {
return return
} }
func BigMax(x, y *big.Int) *big.Int {
if x.Cmp(y) <= 0 {
return x
}
return y
}

View File

@ -38,5 +38,12 @@ var (
Big1 = big.NewInt(1) Big1 = big.NewInt(1)
Big2 = big.NewInt(1) Big2 = big.NewInt(1)
Big0 = big.NewInt(0) Big0 = big.NewInt(0)
Big32 = big.NewInt(32)
Big256 = big.NewInt(0xff) Big256 = big.NewInt(0xff)
) )
func CreateAddress(b []byte, nonce *big.Int) []byte {
addrBytes := append(b, nonce.Bytes()...)
return Sha3Bin(addrBytes)[12:]
}

View File

@ -48,7 +48,7 @@ func ReadConfig(base string) *config {
} }
} }
Config = &config{ExecPath: path, Debug: true, Ver: "0.3.1"} Config = &config{ExecPath: path, Debug: true, Ver: "0.5"}
Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug) Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug)
Config.SetClientString("/Ethereum(G)") Config.SetClientString("/Ethereum(G)")
} }