94 lines
1.9 KiB
Go
94 lines
1.9 KiB
Go
|
package executor
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"log"
|
||
|
"os"
|
||
|
"time"
|
||
|
|
||
|
"github.com/gosuri/uitable"
|
||
|
"github.com/perlin-network/life/compiler"
|
||
|
"github.com/perlin-network/life/exec"
|
||
|
"github.com/rogpeppe/go-internal/txtar"
|
||
|
"within.website/olin/abi/cwa"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
ErrNoCWAMain = errors.New("executor: no cwa_main function defined")
|
||
|
)
|
||
|
|
||
|
type Config struct {
|
||
|
exec.VMConfig
|
||
|
|
||
|
Name string
|
||
|
FuncName string
|
||
|
Env map[string]string
|
||
|
Binary []byte
|
||
|
Stdin io.Reader
|
||
|
Stdout, Stderr io.Writer
|
||
|
LogSink io.Writer
|
||
|
}
|
||
|
|
||
|
type Result struct {
|
||
|
Status int64
|
||
|
GasUsed uint64
|
||
|
SyscallCount int64
|
||
|
ExecDur time.Duration
|
||
|
PagesUsed int
|
||
|
StartTime time.Time
|
||
|
}
|
||
|
|
||
|
func (r Result) ToFile() txtar.File {
|
||
|
table := uitable.New()
|
||
|
|
||
|
table.AddRow("Status", fmt.Sprint(r.Status))
|
||
|
table.AddRow("Gas Used", fmt.Sprint(r.GasUsed))
|
||
|
table.AddRow("Syscall Count", fmt.Sprint(r.SyscallCount))
|
||
|
table.AddRow("Exec Duration", r.ExecDur.String())
|
||
|
table.AddRow("Pages Used", fmt.Sprint(r.PagesUsed))
|
||
|
|
||
|
return txtar.File{
|
||
|
Name: "vmstats.txt",
|
||
|
Data: []byte(table.String()),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Run(c Config) (*Result, error) {
|
||
|
p := cwa.NewProcess(c.Name, nil, c.Env)
|
||
|
p.Stdin = c.Stdin
|
||
|
p.Stdout = c.Stdout
|
||
|
p.Stderr = c.Stderr
|
||
|
p.Logger = log.New(io.MultiWriter(c.LogSink, os.Stdout), c.Name+" ", log.LstdFlags)
|
||
|
|
||
|
gp := &compiler.SimpleGasPolicy{GasPerInstruction: 1}
|
||
|
vm, err := exec.NewVirtualMachine(c.Binary, c.VMConfig, p, gp)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
main, ok := vm.GetFunctionExport(c.FuncName)
|
||
|
if !ok {
|
||
|
return nil, ErrNoCWAMain
|
||
|
}
|
||
|
|
||
|
begin := time.Now()
|
||
|
ret, err := vm.Run(main)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
dur := time.Since(begin)
|
||
|
|
||
|
p.Logger.Printf("[SYSTEM] return status: %v", ret)
|
||
|
|
||
|
return &Result{
|
||
|
Status: ret,
|
||
|
GasUsed: vm.Gas,
|
||
|
SyscallCount: p.SyscallCount(),
|
||
|
ExecDur: dur,
|
||
|
PagesUsed: len(vm.Memory) / 65536,
|
||
|
StartTime: begin,
|
||
|
}, nil
|
||
|
}
|