forked from cerc-io/plugeth
Moving a head closer to interop
This commit is contained in:
parent
c734dde982
commit
8124547348
@ -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 {
|
||||
|
@ -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)
|
||||
*/
|
||||
}
|
||||
|
||||
func (c *StateObject) AddAmount(amount *big.Int) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -47,7 +47,7 @@ func CurrencyToString(num *big.Int) string {
|
||||
// Common big integers often used
|
||||
var (
|
||||
Big1 = big.NewInt(1)
|
||||
Big2 = big.NewInt(1)
|
||||
Big2 = big.NewInt(2)
|
||||
Big0 = big.NewInt(0)
|
||||
Big32 = big.NewInt(32)
|
||||
Big256 = big.NewInt(0xff)
|
||||
|
4
peer.go
4
peer.go
@ -402,7 +402,7 @@ func (p *Peer) HandleInbound() {
|
||||
if err != nil {
|
||||
// If the parent is unknown try to catch up with this peer
|
||||
if ethchain.IsParentErr(err) {
|
||||
ethutil.Config.Log.Infoln("Attempting to catch up since we don't know the parent")
|
||||
ethutil.Config.Log.Infoln("Attempting to catch. Parent known")
|
||||
p.catchingUp = false
|
||||
p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash())
|
||||
} else if ethchain.IsValidationErr(err) {
|
||||
@ -414,7 +414,7 @@ func (p *Peer) HandleInbound() {
|
||||
if p.catchingUp && msg.Data.Len() > 1 {
|
||||
if lastBlock != nil {
|
||||
blockInfo := lastBlock.BlockInfo()
|
||||
ethutil.Config.Log.Debugf("Synced to block height #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash)
|
||||
ethutil.Config.Log.Debugf("Synced chain to #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash)
|
||||
}
|
||||
|
||||
p.catchingUp = false
|
||||
|
Loading…
Reference in New Issue
Block a user