mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 21:26:42 +00:00
wip
This commit is contained in:
parent
f17ae6b256
commit
5027822bde
6 changed files with 77 additions and 66 deletions
|
|
@ -110,8 +110,6 @@ func run(ctx *cli.Context) {
|
|||
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)))
|
||||
|
||||
tstart := time.Now()
|
||||
|
||||
vmstart := time.Now()
|
||||
ret, e := vmenv.Call(
|
||||
sender,
|
||||
receiver.Address(),
|
||||
|
|
@ -120,32 +118,12 @@ func run(ctx *cli.Context) {
|
|||
common.Big(ctx.GlobalString(PriceFlag.Name)),
|
||||
common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||
)
|
||||
vmdone := time.Since(tstart)
|
||||
|
||||
if e != nil {
|
||||
fmt.Println(e)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("no segmentation", time.Since(vmstart))
|
||||
|
||||
fmt.Println()
|
||||
|
||||
if !vm.DisableSegmentation {
|
||||
vmstart = time.Now()
|
||||
ret, e = vmenv.Call(
|
||||
sender,
|
||||
receiver.Address(),
|
||||
common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)),
|
||||
common.Big(ctx.GlobalString(GasFlag.Name)),
|
||||
common.Big(ctx.GlobalString(PriceFlag.Name)),
|
||||
common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||
)
|
||||
|
||||
if e != nil {
|
||||
fmt.Println(e)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("with segmentation", time.Since(vmstart))
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(DumpFlag.Name) {
|
||||
fmt.Println(string(statedb.Dump()))
|
||||
|
|
@ -155,7 +133,7 @@ func run(ctx *cli.Context) {
|
|||
if ctx.GlobalBool(SysStatFlag.Name) {
|
||||
var mem runtime.MemStats
|
||||
runtime.ReadMemStats(&mem)
|
||||
fmt.Printf("vm took %v\n", time.Since(tstart))
|
||||
fmt.Printf("vm took %v\n", vmdone)
|
||||
fmt.Printf(`alloc: %d
|
||||
tot alloc: %d
|
||||
no. malloc: %d
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
)
|
||||
|
||||
func StdErrFormat(logs []StructLog) {
|
||||
fmt.Fprintf(os.Stderr, "VM STAT %d OPs\n", len(logs))
|
||||
for _, log := range logs {
|
||||
fmt.Fprintf(os.Stderr, "PC %08d: %s GAS: %v COST: %v", log.Pc, log.Op, log.Gas, log.GasCost)
|
||||
if log.Err != nil {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ type segment struct {
|
|||
}
|
||||
|
||||
func (c *segment) String() string {
|
||||
return fmt.Sprintf("{%d %d %d %v}", c.cstart, c.cend, c.msize, c.gas)
|
||||
return fmt.Sprintf("{start: %d end: %d ssize: %d gas: %v}", c.cstart, c.cend, c.ssize, c.gas)
|
||||
}
|
||||
|
||||
// native operations
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ func (o OpCode) String() string {
|
|||
|
||||
func isDynamic(op OpCode) bool {
|
||||
switch op {
|
||||
case CREATE, CALL, CALLCODE, JUMP, JUMPI, SUICIDE, STOP, RETURN, EXTCODECOPY, CODECOPY, MSTORE, MSTORE8, SSTORE:
|
||||
case CREATE, CALL, CALLCODE, CALLDATACOPY, GAS, MLOAD, JUMP, JUMPI, SUICIDE, STOP, RETURN, EXTCODECOPY, CODECOPY, MSTORE, MSTORE8, SSTORE:
|
||||
return true
|
||||
}
|
||||
if _, ok := opCodeToString[op]; !ok {
|
||||
|
|
|
|||
105
core/vm/vm.go
105
core/vm/vm.go
|
|
@ -11,6 +11,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var t int
|
||||
|
||||
// Vm implements VirtualMachine
|
||||
type Vm struct {
|
||||
env Environment
|
||||
|
|
@ -38,6 +40,13 @@ func New(env Environment) *Vm {
|
|||
func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
||||
self.env.SetDepth(self.env.Depth() + 1)
|
||||
defer self.env.SetDepth(self.env.Depth() - 1)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
StdErrFormat(self.env.StructLogs())
|
||||
ret = nil
|
||||
err = fmt.Errorf("%v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
var (
|
||||
caller = context.caller
|
||||
|
|
@ -98,17 +107,14 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
ret = context.Return(nil)
|
||||
}
|
||||
|
||||
if csegment != nil && err != nil && csegment.cend == 0 {
|
||||
// delete this tracking segment. We couldn't fully determine the stats
|
||||
delete(csegments, csegment.cstart)
|
||||
} else if csegment != nil && err == nil && csegment.cend == 0 {
|
||||
csegment.cend = pc
|
||||
csegment.ssize = int(math.Abs(math.Min(float64(stack.len()-csegment.ssize), 0)))
|
||||
}
|
||||
|
||||
t, _ := segments.Get(codehash)
|
||||
for _, segment := range t.(codeSegments) {
|
||||
fmt.Println(segment)
|
||||
if !DisableSegmentation && csegment != nil && csegment.cend == 0 {
|
||||
if err != nil {
|
||||
// delete this tracking segment. We couldn't fully determine the stats
|
||||
delete(csegments, csegment.cstart)
|
||||
} else {
|
||||
csegment.cend = pc
|
||||
csegment.ssize = int(math.Abs(math.Min(float64(stack.len()-csegment.ssize), 0)))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
@ -124,27 +130,34 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
}
|
||||
|
||||
for {
|
||||
cost = new(big.Int)
|
||||
// Get the current operation location of pc
|
||||
op = context.GetOp(pc)
|
||||
if !DisableSegmentation {
|
||||
if isDynamic(op) && csegment != nil {
|
||||
// end of segment bound
|
||||
csegment.cend = ppc
|
||||
csegment.next = pc
|
||||
// write out the required required elements on the stack. i.e. the amount of items
|
||||
// required outside of the segment itself.
|
||||
// 0: P, 1
|
||||
// 1: J, 2
|
||||
// 2: D -+
|
||||
// 3: P, 2 |- M,0 = M,0 pushes 1. Requires 2. 1 outside bounds of M,0
|
||||
// 4: ADD -+
|
||||
// 5: J, 2
|
||||
csegment.ssize = int(math.Abs(math.Min(float64(stack.len()-csegment.ssize), 0)))
|
||||
if isDynamic(op) {
|
||||
//fmt.Println("encountered dyn")
|
||||
if csegment != nil && csegment.cend == 0 {
|
||||
//fmt.Println("closing segment with", op, "@", ppc, csegment.gas)
|
||||
// mark end of segment bound
|
||||
csegment.cend = ppc
|
||||
// set the next op for continuation
|
||||
csegment.next = pc
|
||||
// write out the required required elements on the stack. i.e. the amount of items
|
||||
// required outside of the segment itself.
|
||||
// 0: P, 1
|
||||
// 1: J, 2
|
||||
// 2: D -+
|
||||
// 3: P, 2 |- M,0 = M,0 pushes 1. Requires 2. 1 outside bounds of M,0
|
||||
// 4: ADD -+
|
||||
// 5: J, 2
|
||||
csegment.ssize = int(math.Abs(math.Min(float64(stack.len()-csegment.ssize), 0)))
|
||||
}
|
||||
csegment = nil
|
||||
nopay = 0
|
||||
} else if csegment == nil && pc != 0 {
|
||||
// check if a segment is available to us and set it.
|
||||
if seg, ok := csegments[pc]; ok {
|
||||
//fmt.Println(pc, "using seg", seg)
|
||||
nopay = seg.cend
|
||||
|
||||
// make sure there's enough stack items to complete the segment
|
||||
|
|
@ -152,27 +165,36 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
return context.Return(nil), err
|
||||
}
|
||||
|
||||
cost.Set(seg.gas)
|
||||
// use required gas for this segment
|
||||
if !context.UseGas(seg.gas) {
|
||||
context.UseGas(context.Gas)
|
||||
|
||||
return context.Return(nil), OutOfGasError{}
|
||||
}
|
||||
csegment = seg
|
||||
|
||||
for _, operation := range seg.ops {
|
||||
operation.fn(stack, operation.data)
|
||||
}
|
||||
/*
|
||||
for _, operation := range seg.ops {
|
||||
operation.fn(stack, operation.data)
|
||||
}
|
||||
|
||||
pc = seg.next
|
||||
continue
|
||||
pc = seg.next
|
||||
continue
|
||||
*/
|
||||
} else {
|
||||
//fmt.Println("creating", pc)
|
||||
// allocate a new segment for tracking information
|
||||
csegment = &segment{pc, 0, 0, 0, new(big.Int), stack.len(), nil}
|
||||
csegments[pc] = csegment
|
||||
nopay = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// set previous program counter
|
||||
ppc = pc
|
||||
|
||||
//fmt.Println(pc, nopay, pc > nopay, pc == 0)
|
||||
if pc > nopay || pc == 0 || DisableSegmentation {
|
||||
// calculate the new memory size and gas price for the current executing opcode
|
||||
newMemSize, cost, err = self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
|
||||
|
|
@ -180,6 +202,10 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if csegment != nil {
|
||||
csegment.gas.Add(csegment.gas, cost)
|
||||
}
|
||||
|
||||
// Use the calculated gas. When insufficient gas is present, use all gas and return an
|
||||
// Out Of Gas error
|
||||
if !context.UseGas(cost) {
|
||||
|
|
@ -191,15 +217,10 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
// Resize the memory calculated previously
|
||||
mem.Resize(newMemSize.Uint64())
|
||||
|
||||
if csegment != nil {
|
||||
csegment.msize = uint64(len(mem.store))
|
||||
csegment.gas.Add(csegment.gas, cost)
|
||||
}
|
||||
}
|
||||
// Add a log message
|
||||
self.log(pc, op, context.Gas, cost, mem, stack, context, nil)
|
||||
|
||||
ppc = pc
|
||||
// The base for all big integer arithmetic
|
||||
base := new(big.Int)
|
||||
|
||||
|
|
@ -227,12 +248,12 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
case MUL:
|
||||
x, y := stack.pop(), stack.pop()
|
||||
|
||||
base.Mul(x, y)
|
||||
res := new(big.Int).Mul(x, y)
|
||||
|
||||
U256(base)
|
||||
U256(res)
|
||||
|
||||
// pop result back on the stack
|
||||
stack.push(base)
|
||||
stack.push(res)
|
||||
case DIV:
|
||||
x, y := stack.pop(), stack.pop()
|
||||
|
||||
|
|
@ -625,6 +646,10 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
|||
case MSIZE:
|
||||
stack.push(big.NewInt(int64(mem.Len())))
|
||||
case GAS:
|
||||
if t > 1 {
|
||||
//return context.Return(nil), nil
|
||||
}
|
||||
t++
|
||||
stack.push(context.Gas)
|
||||
|
||||
case CREATE:
|
||||
|
|
@ -887,7 +912,9 @@ func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, st
|
|||
mem := make([]byte, len(memory.Data()))
|
||||
copy(mem, memory.Data())
|
||||
stck := make([]*big.Int, len(stack.Data()))
|
||||
copy(stck, stack.Data())
|
||||
for i, item := range stack.Data() {
|
||||
stck[i] = new(big.Int).Set(item)
|
||||
}
|
||||
|
||||
object := context.self.(*state.StateObject)
|
||||
storage := make(map[common.Hash][]byte)
|
||||
|
|
@ -895,7 +922,7 @@ func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, st
|
|||
storage[common.BytesToHash(k)] = v
|
||||
})
|
||||
|
||||
self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, err})
|
||||
self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), new(big.Int).Set(cost), mem, stck, storage, err})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,13 @@ func runStateTests(tests map[string]VmTest, skipTests []string) error {
|
|||
}
|
||||
|
||||
for name, test := range tests {
|
||||
//vm.Debug = true
|
||||
//vm.DisableSegmentation = true
|
||||
/*
|
||||
if name != "Call10" {
|
||||
continue
|
||||
}
|
||||
*/
|
||||
if skipTest[name] {
|
||||
glog.Infoln("Skipping state test", name)
|
||||
return nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue