aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-06-13 22:06:27 +0800
committerobscuren <geffobscura@gmail.com>2014-06-13 22:06:27 +0800
commit81245473486dd680b7121d4b227ca8a57d07b4b1 (patch)
tree0462828a95c3c1af684dc32fdcc15b26772fe762 /ethchain
parentc734dde982c4ce778afa074e94efb09e552dbd84 (diff)
downloaddexon-81245473486dd680b7121d4b227ca8a57d07b4b1.tar
dexon-81245473486dd680b7121d4b227ca8a57d07b4b1.tar.gz
dexon-81245473486dd680b7121d4b227ca8a57d07b4b1.tar.bz2
dexon-81245473486dd680b7121d4b227ca8a57d07b4b1.tar.lz
dexon-81245473486dd680b7121d4b227ca8a57d07b4b1.tar.xz
dexon-81245473486dd680b7121d4b227ca8a57d07b4b1.tar.zst
dexon-81245473486dd680b7121d4b227ca8a57d07b4b1.zip
Moving a head closer to interop
Diffstat (limited to 'ethchain')
-rw-r--r--ethchain/closure.go26
-rw-r--r--ethchain/state_object.go8
-rw-r--r--ethchain/state_transition.go32
-rw-r--r--ethchain/vm.go31
4 files changed, 61 insertions, 36 deletions
diff --git a/ethchain/closure.go b/ethchain/closure.go
index 5c9c3e47c..32b297e90 100644
--- a/ethchain/closure.go
+++ b/ethchain/closure.go
@@ -17,7 +17,7 @@ type ClosureRef interface {
// Basic inline closure object which implement the 'closure' interface
type Closure struct {
- callee ClosureRef
+ caller ClosureRef
object *StateObject
Script []byte
State *State
@@ -28,12 +28,14 @@ type Closure struct {
}
// Create a new closure for the given data items
-func NewClosure(callee ClosureRef, object *StateObject, script []byte, state *State, gas, price *big.Int) *Closure {
- c := &Closure{callee: callee, object: object, Script: script, State: state, Args: nil}
+func NewClosure(caller ClosureRef, object *StateObject, script []byte, state *State, gas, price *big.Int) *Closure {
+ c := &Closure{caller: caller, object: object, Script: script, State: state, Args: nil}
- // In most cases gas, price and value are pointers to transaction objects
+ // 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.Gas = new(big.Int).Set(gas)
c.Price = new(big.Int).Set(price)
c.UsedGas = new(big.Int)
@@ -83,11 +85,11 @@ func (c *Closure) Call(vm *Vm, args []byte, hook DebugHook) ([]byte, *big.Int, e
}
func (c *Closure) Return(ret []byte) []byte {
- // Return the remaining gas to the callee
- // If no callee is present return it to
+ // Return the remaining gas to the caller
+ // If no caller is present return it to
// the origin (i.e. contract or tx)
- if c.callee != nil {
- c.callee.ReturnGas(c.Gas, c.Price, c.State)
+ if c.caller != nil {
+ c.caller.ReturnGas(c.Gas, c.Price, c.State)
} else {
c.object.ReturnGas(c.Gas, c.Price, c.State)
}
@@ -107,7 +109,7 @@ func (c *Closure) UseGas(gas *big.Int) bool {
return true
}
-// Implement the Callee interface
+// Implement the caller interface
func (c *Closure) ReturnGas(gas, price *big.Int, state *State) {
// Return the gas to the closure
c.Gas.Add(c.Gas, gas)
@@ -118,8 +120,8 @@ func (c *Closure) Object() *StateObject {
return c.object
}
-func (c *Closure) Callee() ClosureRef {
- return c.callee
+func (c *Closure) Caller() ClosureRef {
+ return c.caller
}
func (c *Closure) N() *big.Int {
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index b92374882..12ebf8e9b 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -77,7 +77,7 @@ func (c *StateObject) SetAddr(addr []byte, value interface{}) {
func (c *StateObject) SetStorage(num *big.Int, val *ethutil.Value) {
addr := ethutil.BigToBytes(num, 256)
- //fmt.Println("storing", val.BigInt(), "@", num)
+ //fmt.Printf("sstore %x => %v\n", addr, val)
c.SetAddr(addr, val)
}
@@ -102,8 +102,10 @@ func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
// Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *StateObject) ReturnGas(gas, price *big.Int, state *State) {
- remainder := new(big.Int).Mul(gas, price)
- c.AddAmount(remainder)
+ /*
+ remainder := new(big.Int).Mul(gas, price)
+ c.AddAmount(remainder)
+ */
}
func (c *StateObject) AddAmount(amount *big.Int) {
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 1256d019c..a080c5602 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -116,7 +116,7 @@ func (self *StateTransition) TransitionState() (err error) {
defer func() {
if r := recover(); r != nil {
ethutil.Config.Log.Infoln(r)
- err = fmt.Errorf("%v", r)
+ err = fmt.Errorf("state transition err %v", r)
}
}()
@@ -126,41 +126,51 @@ func (self *StateTransition) TransitionState() (err error) {
receiver *StateObject
)
+ // Make sure this transaction's nonce is correct
if sender.Nonce != tx.Nonce {
return NonceError(tx.Nonce, sender.Nonce)
}
+ // Increment the nonce for the next transaction
sender.Nonce += 1
+ // Pre-pay gas / Buy gas of the coinbase account
if err = self.BuyGas(); err != nil {
return err
}
+ // Get the receiver (TODO fix this, if coinbase is the receiver we need to save/retrieve)
receiver = self.Receiver()
+ // Transaction gas
if err = self.UseGas(GasTx); err != nil {
return err
}
+ // Pay data gas
dataPrice := big.NewInt(int64(len(tx.Data)))
dataPrice.Mul(dataPrice, GasData)
if err = self.UseGas(dataPrice); err != nil {
return err
}
- if receiver == nil { // Contract
+ // If the receiver is nil it's a contract (\0*32).
+ if receiver == nil {
+ // Create a new state object for the contract
receiver = self.MakeStateObject(self.state, tx)
if receiver == nil {
return fmt.Errorf("ERR. Unable to create contract with transaction %v", tx)
}
}
+ // Transfer value from sender to receiver
if err = self.transferValue(sender, receiver); err != nil {
return err
}
+ // Process the init code and create 'valid' contract
if tx.CreatesContract() {
- fmt.Println(Disassemble(receiver.Init()))
+ //fmt.Println(Disassemble(receiver.Init()))
// Evaluate the initialization script
// and use the return value as the
// script section for the state object.
@@ -173,6 +183,10 @@ func (self *StateTransition) TransitionState() (err error) {
receiver.script = code
}
+ // Return remaining gas
+ remaining := new(big.Int).Mul(self.gas, tx.GasPrice)
+ sender.AddAmount(remaining)
+
self.state.UpdateStateObject(sender)
self.state.UpdateStateObject(receiver)
@@ -184,12 +198,14 @@ func (self *StateTransition) transferValue(sender, receiver *StateObject) error
return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.tx.Value, sender.Amount)
}
- // Subtract the amount from the senders account
- sender.SubAmount(self.tx.Value)
- // Add the amount to receivers account which should conclude this transaction
- receiver.AddAmount(self.tx.Value)
+ if self.tx.Value.Cmp(ethutil.Big0) > 0 {
+ // Subtract the amount from the senders account
+ sender.SubAmount(self.tx.Value)
+ // Add the amount to receivers account which should conclude this transaction
+ receiver.AddAmount(self.tx.Value)
- ethutil.Config.Log.Debugf("%x => %x (%v) %x\n", sender.Address()[:4], receiver.Address()[:4], self.tx.Value, self.tx.Hash())
+ ethutil.Config.Log.Debugf("%x => %x (%v) %x\n", sender.Address()[:4], receiver.Address()[:4], self.tx.Value, self.tx.Hash())
+ }
return nil
}
diff --git a/ethchain/vm.go b/ethchain/vm.go
index e17264697..f0059f6ac 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -114,14 +114,18 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
gas := new(big.Int)
- setStepGasUsage := func(amount *big.Int) {
+ addStepGasUsage := func(amount *big.Int) {
gas.Add(gas, amount)
}
+ addStepGasUsage(GasStep)
+
var newMemSize uint64 = 0
switch op {
+ case STOP:
+ case SUICIDE:
case SLOAD:
- setStepGasUsage(GasSLoad)
+ gas.Set(GasSLoad)
case SSTORE:
var mult *big.Int
y, x := stack.Peekn()
@@ -133,12 +137,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
} else {
mult = ethutil.Big1
}
- setStepGasUsage(new(big.Int).Mul(mult, GasSStore))
+ gas = new(big.Int).Mul(mult, GasSStore)
case BALANCE:
- setStepGasUsage(GasBalance)
+ gas.Set(GasBalance)
case MSTORE:
require(2)
newMemSize = stack.Peek().Uint64() + 32
+ case MLOAD:
+
case MSTORE8:
require(2)
newMemSize = stack.Peek().Uint64() + 1
@@ -149,7 +155,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case SHA3:
require(2)
- setStepGasUsage(GasSha)
+ gas.Set(GasSha)
newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64()
case CALLDATACOPY:
@@ -162,7 +168,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64()
case CALL:
require(7)
- setStepGasUsage(GasCall)
+ gas.Set(GasCall)
+ addStepGasUsage(stack.data[stack.Len()-1])
x := stack.data[stack.Len()-6].Uint64() + stack.data[stack.Len()-7].Uint64()
y := stack.data[stack.Len()-4].Uint64() + stack.data[stack.Len()-5].Uint64()
@@ -170,17 +177,15 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
newMemSize = uint64(math.Max(float64(x), float64(y)))
case CREATE:
require(3)
- setStepGasUsage(GasCreate)
+ gas.Set(GasCreate)
newMemSize = stack.data[stack.Len()-2].Uint64() + stack.data[stack.Len()-3].Uint64()
- default:
- setStepGasUsage(GasStep)
}
newMemSize = (newMemSize + 31) / 32 * 32
if newMemSize > uint64(mem.Len()) {
m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32
- setStepGasUsage(big.NewInt(int64(m)))
+ addStepGasUsage(big.NewInt(int64(m)))
}
if !closure.UseGas(gas) {
@@ -355,7 +360,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin))
case CALLER:
- stack.Push(ethutil.BigD(closure.Callee().Address()))
+ stack.Push(ethutil.BigD(closure.caller.Address()))
case CALLVALUE:
stack.Push(vm.vars.Value)
case CALLDATALOAD:
@@ -492,7 +497,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
snapshot := vm.state.Snapshot()
// Generate a new address
- addr := ethutil.CreateAddress(closure.callee.Address(), closure.callee.N())
+ addr := ethutil.CreateAddress(closure.caller.Address(), closure.caller.N())
// Create a new contract
contract := NewContract(addr, value, []byte(""))
// Set the init script
@@ -503,7 +508,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
//closure.UseGas(gas)
// Create the closure
- c := NewClosure(closure.callee,
+ c := NewClosure(closure.caller,
closure.Object(),
contract.initScript,
vm.state,