mirror of https://github.com/status-im/op-geth.git
Fixed MSTORE and added some more commets
This commit is contained in:
parent
f21eb88ad1
commit
c68ff9886b
|
@ -21,15 +21,17 @@ type ClosureBody interface {
|
||||||
type Closure struct {
|
type Closure struct {
|
||||||
callee Callee
|
callee Callee
|
||||||
object ClosureBody
|
object ClosureBody
|
||||||
state *State
|
State *State
|
||||||
|
|
||||||
gas *big.Int
|
gas *big.Int
|
||||||
val *big.Int
|
val *big.Int
|
||||||
|
|
||||||
|
args []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new closure for the given data items
|
// Create a new closure for the given data items
|
||||||
func NewClosure(callee Callee, object ClosureBody, state *State, gas, val *big.Int) *Closure {
|
func NewClosure(callee Callee, object ClosureBody, state *State, gas, val *big.Int) *Closure {
|
||||||
return &Closure{callee, object, state, gas, val}
|
return &Closure{callee, object, state, gas, val, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retuns the x element in data slice
|
// Retuns the x element in data slice
|
||||||
|
@ -42,14 +44,20 @@ func (c *Closure) GetMem(x int64) *ethutil.Value {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Closure) Call(vm *Vm, args []byte) []byte {
|
||||||
|
c.args = args
|
||||||
|
|
||||||
|
return vm.RunClosure(c)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Closure) Return(ret []byte) []byte {
|
func (c *Closure) Return(ret []byte) []byte {
|
||||||
// Return the remaining gas to the callee
|
// Return the remaining gas to the callee
|
||||||
// If no callee is present return it to
|
// If no callee is present return it to
|
||||||
// the origin (i.e. contract or tx)
|
// the origin (i.e. contract or tx)
|
||||||
if c.callee != nil {
|
if c.callee != nil {
|
||||||
c.callee.ReturnGas(c.gas, c.state)
|
c.callee.ReturnGas(c.gas, c.State)
|
||||||
} else {
|
} else {
|
||||||
c.object.ReturnGas(c.gas, c.state)
|
c.object.ReturnGas(c.gas, c.State)
|
||||||
// TODO incase it's a POST contract we gotta serialise the contract again.
|
// TODO incase it's a POST contract we gotta serialise the contract again.
|
||||||
// But it's not yet defined
|
// But it's not yet defined
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,6 +235,7 @@ func (st *ValueStack) Peekn() (*ethutil.Value, *ethutil.Value) {
|
||||||
func (st *ValueStack) Push(d *ethutil.Value) {
|
func (st *ValueStack) Push(d *ethutil.Value) {
|
||||||
st.data = append(st.data, d)
|
st.data = append(st.data, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ValueStack) Print() {
|
func (st *ValueStack) Print() {
|
||||||
fmt.Println("### STACK ###")
|
fmt.Println("### STACK ###")
|
||||||
if len(st.data) > 0 {
|
if len(st.data) > 0 {
|
||||||
|
|
|
@ -18,6 +18,8 @@ type Vm struct {
|
||||||
mem map[string]*big.Int
|
mem map[string]*big.Int
|
||||||
|
|
||||||
vars RuntimeVars
|
vars RuntimeVars
|
||||||
|
|
||||||
|
state *State
|
||||||
}
|
}
|
||||||
|
|
||||||
type RuntimeVars struct {
|
type RuntimeVars struct {
|
||||||
|
@ -32,7 +34,11 @@ type RuntimeVars struct {
|
||||||
txData []string
|
txData []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *Vm) RunClosure(closure *Closure, state *State, vars RuntimeVars) []byte {
|
func NewVm(state *State, vars RuntimeVars) *Vm {
|
||||||
|
return &Vm{vars: vars, state: state}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *Vm) RunClosure(closure *Closure) []byte {
|
||||||
// If the amount of gas supplied is less equal to 0
|
// If the amount of gas supplied is less equal to 0
|
||||||
if closure.GetGas().Cmp(big.NewInt(0)) <= 0 {
|
if closure.GetGas().Cmp(big.NewInt(0)) <= 0 {
|
||||||
// TODO Do something
|
// TODO Do something
|
||||||
|
@ -71,17 +77,28 @@ func (vm *Vm) RunClosure(closure *Closure, state *State, vars RuntimeVars) []byt
|
||||||
}
|
}
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
case oSTOP:
|
case oSTOP: // Stop the closure
|
||||||
return closure.Return(nil)
|
return closure.Return(nil)
|
||||||
case oPUSH:
|
case oPUSH: // Push PC+1 on to the stack
|
||||||
pc++
|
pc++
|
||||||
val := closure.GetMem(pc).BigInt()
|
val := closure.GetMem(pc).BigInt()
|
||||||
stack.Push(val)
|
stack.Push(val)
|
||||||
case oMSTORE:
|
case oMSTORE: // Store the value at stack top-1 in to memory at location stack top
|
||||||
// Pop value of the stack
|
// Pop value of the stack
|
||||||
val := stack.Pop()
|
val, mStart := stack.Popn()
|
||||||
// Set the bytes to the memory field
|
// Ensure that memory is large enough to hold the data
|
||||||
mem = append(mem, ethutil.BigToBytes(val, 256)...)
|
// If it isn't resize the memory slice so that it may hold the value
|
||||||
|
bytesLen := big.NewInt(32)
|
||||||
|
totSize := new(big.Int).Add(mStart, bytesLen)
|
||||||
|
lenSize := big.NewInt(int64(len(mem)))
|
||||||
|
if totSize.Cmp(lenSize) > 0 {
|
||||||
|
// Calculate the diff between the sizes
|
||||||
|
diff := new(big.Int).Sub(totSize, lenSize)
|
||||||
|
// Create a new empty slice and append it
|
||||||
|
newSlice := make([]byte, diff.Int64()+1)
|
||||||
|
mem = append(mem, newSlice...)
|
||||||
|
}
|
||||||
|
copy(mem[mStart.Int64():mStart.Int64()+bytesLen.Int64()+1], ethutil.BigToBytes(val, 256))
|
||||||
case oCALL:
|
case oCALL:
|
||||||
// Pop return size and offset
|
// Pop return size and offset
|
||||||
retSize, retOffset := stack.Popn()
|
retSize, retOffset := stack.Popn()
|
||||||
|
@ -93,20 +110,25 @@ func (vm *Vm) RunClosure(closure *Closure, state *State, vars RuntimeVars) []byt
|
||||||
gas, value := stack.Popn()
|
gas, value := stack.Popn()
|
||||||
// Closure addr
|
// Closure addr
|
||||||
addr := stack.Pop()
|
addr := stack.Pop()
|
||||||
|
// Fetch the contract which will serve as the closure body
|
||||||
contract := state.GetContract(addr.Bytes())
|
contract := vm.state.GetContract(addr.Bytes())
|
||||||
closure := NewClosure(closure, contract, state, gas, value)
|
// Create a new callable closure
|
||||||
ret := vm.RunClosure(closure, state, vars)
|
closure := NewClosure(closure, contract, vm.state, gas, value)
|
||||||
|
// Executer the closure and get the return value (if any)
|
||||||
|
ret := closure.Call(vm, nil)
|
||||||
|
|
||||||
// Ensure that memory is large enough to hold the returned data
|
// Ensure that memory is large enough to hold the returned data
|
||||||
|
// If it isn't resize the memory slice so that it may hold the value
|
||||||
totSize := new(big.Int).Add(retOffset, retSize)
|
totSize := new(big.Int).Add(retOffset, retSize)
|
||||||
lenSize := big.NewInt(int64(len(mem)))
|
lenSize := big.NewInt(int64(len(mem)))
|
||||||
// Resize the current memory slice so that the return value may fit
|
|
||||||
if totSize.Cmp(lenSize) > 0 {
|
if totSize.Cmp(lenSize) > 0 {
|
||||||
|
// Calculate the diff between the sizes
|
||||||
diff := new(big.Int).Sub(totSize, lenSize)
|
diff := new(big.Int).Sub(totSize, lenSize)
|
||||||
|
// Create a new empty slice and append it
|
||||||
newSlice := make([]byte, diff.Int64()+1)
|
newSlice := make([]byte, diff.Int64()+1)
|
||||||
mem = append(mem, newSlice...)
|
mem = append(mem, newSlice...)
|
||||||
}
|
}
|
||||||
|
// Copy over the returned values to the memory given the offset and size
|
||||||
copy(mem[retOffset.Int64():retOffset.Int64()+retSize.Int64()+1], ret)
|
copy(mem[retOffset.Int64():retOffset.Int64()+retSize.Int64()+1], ret)
|
||||||
case oRETURN:
|
case oRETURN:
|
||||||
size, offset := stack.Popn()
|
size, offset := stack.Popn()
|
||||||
|
|
|
@ -117,8 +117,10 @@ func TestRun3(t *testing.T) {
|
||||||
|
|
||||||
script := Compile([]string{
|
script := Compile([]string{
|
||||||
"PUSH", "300",
|
"PUSH", "300",
|
||||||
|
"PUSH", "0",
|
||||||
"MSTORE",
|
"MSTORE",
|
||||||
"PUSH", "300",
|
"PUSH", "300",
|
||||||
|
"PUSH", "31",
|
||||||
"MSTORE",
|
"MSTORE",
|
||||||
"PUSH", "62",
|
"PUSH", "62",
|
||||||
"PUSH", "0",
|
"PUSH", "0",
|
||||||
|
@ -147,8 +149,7 @@ func TestRun3(t *testing.T) {
|
||||||
executer.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
|
executer.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
|
||||||
callerClosure := NewClosure(executer, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))
|
callerClosure := NewClosure(executer, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))
|
||||||
|
|
||||||
vm := &Vm{}
|
vm := NewVm(state, RuntimeVars{
|
||||||
vm.RunClosure(callerClosure, state, RuntimeVars{
|
|
||||||
address: callerAddr,
|
address: callerAddr,
|
||||||
blockNumber: 1,
|
blockNumber: 1,
|
||||||
sender: ethutil.FromHex("cd1722f3947def4cf144679da39c4c32bdc35681"),
|
sender: ethutil.FromHex("cd1722f3947def4cf144679da39c4c32bdc35681"),
|
||||||
|
@ -159,4 +160,5 @@ func TestRun3(t *testing.T) {
|
||||||
txValue: big.NewInt(10000),
|
txValue: big.NewInt(10000),
|
||||||
txData: nil,
|
txData: nil,
|
||||||
})
|
})
|
||||||
|
callerClosure.Call(vm, nil)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue