From 20c742e47406c13ebc6427951f6fcf1b0056ea26 Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 18 Oct 2014 13:31:20 +0200 Subject: Moved ethvm => vm --- vm/closure.go | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 vm/closure.go (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go new file mode 100644 index 000000000..5a1e1d4d5 --- /dev/null +++ b/vm/closure.go @@ -0,0 +1,140 @@ +package vm + +// TODO Re write VM to use values instead of big integers? + +import ( + "math/big" + + "github.com/ethereum/eth-go/ethstate" + "github.com/ethereum/eth-go/ethutil" +) + +type ClosureRef interface { + ReturnGas(*big.Int, *big.Int) + Address() []byte + Object() *ethstate.StateObject + GetStorage(*big.Int) *ethutil.Value + SetStorage(*big.Int, *ethutil.Value) +} + +// Basic inline closure object which implement the 'closure' interface +type Closure struct { + caller ClosureRef + object *ethstate.StateObject + Code []byte + message *ethstate.Message + exe *Execution + + Gas, UsedGas, Price *big.Int + + Args []byte +} + +// Create a new closure for the given data items +func NewClosure(msg *ethstate.Message, caller ClosureRef, object *ethstate.StateObject, code []byte, gas, price *big.Int) *Closure { + c := &Closure{message: msg, caller: caller, object: object, Code: code, Args: nil} + + // Gas should be a pointer so it can safely be reduced through the run + // This pointer will be off the state transition + c.Gas = gas //new(big.Int).Set(gas) + // In most cases price and value are pointers to transaction objects + // and we don't want the transaction's values to change. + c.Price = new(big.Int).Set(price) + c.UsedGas = new(big.Int) + + return c +} + +// Retuns the x element in data slice +func (c *Closure) GetStorage(x *big.Int) *ethutil.Value { + m := c.object.GetStorage(x) + if m == nil { + return ethutil.EmptyValue() + } + + return m +} + +func (c *Closure) Get(x *big.Int) *ethutil.Value { + return c.Gets(x, big.NewInt(1)) +} + +func (c *Closure) GetOp(x int) OpCode { + return OpCode(c.GetByte(x)) +} + +func (c *Closure) GetByte(x int) byte { + if x < len(c.Code) { + return c.Code[x] + } + + return 0 +} + +func (c *Closure) GetBytes(x, y int) []byte { + if x >= len(c.Code) || y >= len(c.Code) { + return nil + } + + return c.Code[x : x+y] +} + +func (c *Closure) Gets(x, y *big.Int) *ethutil.Value { + if x.Int64() >= int64(len(c.Code)) || y.Int64() >= int64(len(c.Code)) { + return ethutil.NewValue(0) + } + + partial := c.Code[x.Int64() : x.Int64()+y.Int64()] + + return ethutil.NewValue(partial) +} + +func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) { + c.object.SetStorage(x, val) +} + +func (c *Closure) Address() []byte { + return c.object.Address() +} + +func (c *Closure) Call(vm VirtualMachine, args []byte) ([]byte, *big.Int, error) { + c.Args = args + + ret, err := vm.RunClosure(c) + + return ret, c.UsedGas, err +} + +func (c *Closure) Return(ret []byte) []byte { + // Return the remaining gas to the caller + c.caller.ReturnGas(c.Gas, c.Price) + + return ret +} + +func (c *Closure) UseGas(gas *big.Int) bool { + if c.Gas.Cmp(gas) < 0 { + return false + } + + // Sub the amount of gas from the remaining + c.Gas.Sub(c.Gas, gas) + c.UsedGas.Add(c.UsedGas, gas) + + return true +} + +// Implement the caller interface +func (c *Closure) ReturnGas(gas, price *big.Int) { + // Return the gas to the closure + c.Gas.Add(c.Gas, gas) + c.UsedGas.Sub(c.UsedGas, gas) +} + +func (c *Closure) Object() *ethstate.StateObject { + return c.object +} + +func (c *Closure) Caller() ClosureRef { + return c.caller +} -- cgit From af8f5f0b69f1c359991d12c7708804fe8dd1f944 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 31 Oct 2014 14:43:14 +0100 Subject: ethstate => state --- vm/closure.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index b556bc03d..8e54e9ce6 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -5,14 +5,14 @@ package vm import ( "math/big" - "github.com/ethereum/go-ethereum/ethstate" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" ) type ClosureRef interface { ReturnGas(*big.Int, *big.Int) Address() []byte - Object() *ethstate.StateObject + Object() *state.StateObject GetStorage(*big.Int) *ethutil.Value SetStorage(*big.Int, *ethutil.Value) } @@ -20,9 +20,9 @@ type ClosureRef interface { // Basic inline closure object which implement the 'closure' interface type Closure struct { caller ClosureRef - object *ethstate.StateObject + object *state.StateObject Code []byte - message *ethstate.Message + message *state.Message exe *Execution Gas, UsedGas, Price *big.Int @@ -31,7 +31,7 @@ type Closure struct { } // Create a new closure for the given data items -func NewClosure(msg *ethstate.Message, caller ClosureRef, object *ethstate.StateObject, code []byte, gas, price *big.Int) *Closure { +func NewClosure(msg *state.Message, caller ClosureRef, object *state.StateObject, code []byte, gas, price *big.Int) *Closure { c := &Closure{message: msg, caller: caller, object: object, Code: code, Args: nil} // Gas should be a pointer so it can safely be reduced through the run @@ -131,7 +131,7 @@ func (c *Closure) ReturnGas(gas, price *big.Int) { c.UsedGas.Sub(c.UsedGas, gas) } -func (c *Closure) Object() *ethstate.StateObject { +func (c *Closure) Object() *state.StateObject { return c.object } -- cgit From 60cdb1148c404218846fd39331690658168f4e04 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 12 Nov 2014 01:36:36 +0100 Subject: Transaction execution fixes --- vm/closure.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index 8e54e9ce6..ef9bbca93 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -138,3 +138,7 @@ func (c *Closure) Object() *state.StateObject { func (c *Closure) Caller() ClosureRef { return c.caller } + +func (self *Closure) SetExecution(exe *Execution) { + self.exe = exe +} -- cgit From a22056db5988bfa2b1354e0092eabb734c30701c Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 1 Dec 2014 20:49:56 +0100 Subject: Make an attempt to pay for the gas prior to expanding the mem. --- vm/closure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index ef9bbca93..5bd8c1bb8 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -64,7 +64,7 @@ func (c *Closure) GetOp(x int) OpCode { } func (c *Closure) GetByte(x int) byte { - if x < len(c.Code) { + if x > -1 && x < len(c.Code) { return c.Code[x] } -- cgit From 99853ac3ce57807deb4822dd324186e1d2ee0821 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 3 Dec 2014 17:06:54 +0100 Subject: Moved execution from vm to chain. This moves call and create to the specified environments. Vms are no longer re-used. Vm uses environment's Call(Code) and Create in order to execute new contracts or transfer value between accounts. State transition now uses the same mechanism described above. --- vm/closure.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index 5bd8c1bb8..2263236e7 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -12,7 +12,7 @@ import ( type ClosureRef interface { ReturnGas(*big.Int, *big.Int) Address() []byte - Object() *state.StateObject + SetCode([]byte) GetStorage(*big.Int) *ethutil.Value SetStorage(*big.Int, *ethutil.Value) } @@ -20,10 +20,9 @@ type ClosureRef interface { // Basic inline closure object which implement the 'closure' interface type Closure struct { caller ClosureRef - object *state.StateObject + object ClosureRef Code []byte message *state.Message - exe *Execution Gas, UsedGas, Price *big.Int @@ -31,7 +30,7 @@ type Closure struct { } // Create a new closure for the given data items -func NewClosure(msg *state.Message, caller ClosureRef, object *state.StateObject, code []byte, gas, price *big.Int) *Closure { +func NewClosure(msg *state.Message, caller ClosureRef, object ClosureRef, code []byte, gas, price *big.Int) *Closure { c := &Closure{message: msg, caller: caller, object: object, Code: code, Args: nil} // Gas should be a pointer so it can safely be reduced through the run @@ -89,6 +88,10 @@ func (c *Closure) Gets(x, y *big.Int) *ethutil.Value { return ethutil.NewValue(partial) } +func (self *Closure) SetCode(code []byte) { + self.Code = code +} + func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) { c.object.SetStorage(x, val) } @@ -97,6 +100,7 @@ func (c *Closure) Address() []byte { return c.object.Address() } +/* func (c *Closure) Call(vm VirtualMachine, args []byte) ([]byte, *big.Int, error) { c.Args = args @@ -104,6 +108,7 @@ func (c *Closure) Call(vm VirtualMachine, args []byte) ([]byte, *big.Int, error) return ret, c.UsedGas, err } +*/ func (c *Closure) Return(ret []byte) []byte { // Return the remaining gas to the caller @@ -131,14 +136,6 @@ func (c *Closure) ReturnGas(gas, price *big.Int) { c.UsedGas.Sub(c.UsedGas, gas) } -func (c *Closure) Object() *state.StateObject { - return c.object -} - func (c *Closure) Caller() ClosureRef { return c.caller } - -func (self *Closure) SetExecution(exe *Execution) { - self.exe = exe -} -- cgit From b6cb5272de96185b424d5c6c4a817d99f536d29b Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 3 Dec 2014 17:35:57 +0100 Subject: Descriptive function names for closure getters --- vm/closure.go | 57 ++++++++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index 2263236e7..5324ee1ec 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -1,7 +1,5 @@ package vm -// TODO Re write VM to use values instead of big integers? - import ( "math/big" @@ -17,7 +15,6 @@ type ClosureRef interface { SetStorage(*big.Int, *ethutil.Value) } -// Basic inline closure object which implement the 'closure' interface type Closure struct { caller ClosureRef object ClosureRef @@ -44,18 +41,8 @@ func NewClosure(msg *state.Message, caller ClosureRef, object ClosureRef, code [ return c } -// Retuns the x element in data slice -func (c *Closure) GetStorage(x *big.Int) *ethutil.Value { - m := c.object.GetStorage(x) - if m == nil { - return ethutil.EmptyValue() - } - - return m -} - -func (c *Closure) Get(x *big.Int) *ethutil.Value { - return c.Gets(x, big.NewInt(1)) +func (c *Closure) GetValue(x *big.Int) *ethutil.Value { + return c.GetRangeValue(x, big.NewInt(1)) } func (c *Closure) GetOp(x int) OpCode { @@ -78,7 +65,7 @@ func (c *Closure) GetBytes(x, y int) []byte { return c.Code[x : x+y] } -func (c *Closure) Gets(x, y *big.Int) *ethutil.Value { +func (c *Closure) GetRangeValue(x, y *big.Int) *ethutil.Value { if x.Int64() >= int64(len(c.Code)) || y.Int64() >= int64(len(c.Code)) { return ethutil.NewValue(0) } @@ -88,27 +75,21 @@ func (c *Closure) Gets(x, y *big.Int) *ethutil.Value { return ethutil.NewValue(partial) } -func (self *Closure) SetCode(code []byte) { - self.Code = code -} - +/* + * State storage functions + */ func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) { c.object.SetStorage(x, val) } -func (c *Closure) Address() []byte { - return c.object.Address() -} - -/* -func (c *Closure) Call(vm VirtualMachine, args []byte) ([]byte, *big.Int, error) { - c.Args = args - - ret, err := vm.RunClosure(c) +func (c *Closure) GetStorage(x *big.Int) *ethutil.Value { + m := c.object.GetStorage(x) + if m == nil { + return ethutil.EmptyValue() + } - return ret, c.UsedGas, err + return m } -*/ func (c *Closure) Return(ret []byte) []byte { // Return the remaining gas to the caller @@ -117,6 +98,9 @@ func (c *Closure) Return(ret []byte) []byte { return ret } +/* + * Gas functions + */ func (c *Closure) UseGas(gas *big.Int) bool { if c.Gas.Cmp(gas) < 0 { return false @@ -136,6 +120,17 @@ func (c *Closure) ReturnGas(gas, price *big.Int) { c.UsedGas.Sub(c.UsedGas, gas) } +/* + * Set / Get + */ func (c *Closure) Caller() ClosureRef { return c.caller } + +func (c *Closure) Address() []byte { + return c.object.Address() +} + +func (self *Closure) SetCode(code []byte) { + self.Code = code +} -- cgit From 83663ed4b01480c628ce2c849e4e881ac04b5120 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 4 Dec 2014 10:53:49 +0100 Subject: Renames for chain, updated VM, moved methods * Renamed a couple more chain => core * Updated VM `pc` to be uint64 rather than big int * XEth interface cleanup --- vm/closure.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index 5324ee1ec..bd5268f96 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -41,16 +41,16 @@ func NewClosure(msg *state.Message, caller ClosureRef, object ClosureRef, code [ return c } -func (c *Closure) GetValue(x *big.Int) *ethutil.Value { - return c.GetRangeValue(x, big.NewInt(1)) +func (c *Closure) GetValue(x uint64) *ethutil.Value { + return c.GetRangeValue(x, 1) } -func (c *Closure) GetOp(x int) OpCode { +func (c *Closure) GetOp(x uint64) OpCode { return OpCode(c.GetByte(x)) } -func (c *Closure) GetByte(x int) byte { - if x > -1 && x < len(c.Code) { +func (c *Closure) GetByte(x uint64) byte { + if x < uint64(len(c.Code)) { return c.Code[x] } @@ -65,12 +65,12 @@ func (c *Closure) GetBytes(x, y int) []byte { return c.Code[x : x+y] } -func (c *Closure) GetRangeValue(x, y *big.Int) *ethutil.Value { - if x.Int64() >= int64(len(c.Code)) || y.Int64() >= int64(len(c.Code)) { +func (c *Closure) GetRangeValue(x, y uint64) *ethutil.Value { + if x >= uint64(len(c.Code)) || y >= uint64(len(c.Code)) { return ethutil.NewValue(0) } - partial := c.Code[x.Int64() : x.Int64()+y.Int64()] + partial := c.Code[x : x+y] return ethutil.NewValue(partial) } -- cgit From 59ef6e36931c980ba15babfb3680514635faebf6 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 19 Dec 2014 00:18:52 +0100 Subject: Cleaned up objects --- vm/closure.go | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) (limited to 'vm/closure.go') diff --git a/vm/closure.go b/vm/closure.go index bd5268f96..97b31ada0 100644 --- a/vm/closure.go +++ b/vm/closure.go @@ -3,7 +3,6 @@ package vm import ( "math/big" - "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" ) @@ -11,8 +10,6 @@ type ClosureRef interface { ReturnGas(*big.Int, *big.Int) Address() []byte SetCode([]byte) - GetStorage(*big.Int) *ethutil.Value - SetStorage(*big.Int, *ethutil.Value) } type Closure struct { @@ -41,10 +38,6 @@ func NewClosure(msg *state.Message, caller ClosureRef, object ClosureRef, code [ return c } -func (c *Closure) GetValue(x uint64) *ethutil.Value { - return c.GetRangeValue(x, 1) -} - func (c *Closure) GetOp(x uint64) OpCode { return OpCode(c.GetByte(x)) } @@ -65,30 +58,12 @@ func (c *Closure) GetBytes(x, y int) []byte { return c.Code[x : x+y] } -func (c *Closure) GetRangeValue(x, y uint64) *ethutil.Value { +func (c *Closure) GetRangeValue(x, y uint64) []byte { if x >= uint64(len(c.Code)) || y >= uint64(len(c.Code)) { - return ethutil.NewValue(0) - } - - partial := c.Code[x : x+y] - - return ethutil.NewValue(partial) -} - -/* - * State storage functions - */ -func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) { - c.object.SetStorage(x, val) -} - -func (c *Closure) GetStorage(x *big.Int) *ethutil.Value { - m := c.object.GetStorage(x) - if m == nil { - return ethutil.EmptyValue() + return nil } - return m + return c.Code[x : x+y] } func (c *Closure) Return(ret []byte) []byte { @@ -123,10 +98,6 @@ func (c *Closure) ReturnGas(gas, price *big.Int) { /* * Set / Get */ -func (c *Closure) Caller() ClosureRef { - return c.caller -} - func (c *Closure) Address() []byte { return c.object.Address() } -- cgit