58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
package covertest
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
|
)
|
|
|
|
// InstrHash maps instruction with scripthash of a contract it belongs to.
|
|
type InstrHash struct {
|
|
Offset int
|
|
Instruction opcode.Opcode
|
|
ScriptHash util.Uint160
|
|
}
|
|
|
|
// Run starts execution of the loaded program and accumulates all seen opcodes
|
|
// together with the scripthash of a contract they belong to.
|
|
// Original vm.Run(): https://github.com/nspcc-dev/neo-go/blob/v0.101.3/pkg/vm/vm.go#L418
|
|
func Run(v *vm.VM) ([]InstrHash, error) {
|
|
if !v.Ready() {
|
|
return nil, errors.New("no program loaded")
|
|
}
|
|
|
|
if v.HasFailed() {
|
|
// VM already ran something and failed, in general its state is
|
|
// undefined in this case so we can't run anything.
|
|
return nil, errors.New("VM has failed")
|
|
}
|
|
|
|
// vmstate.Halt (the default) or vmstate.Break are safe to continue.
|
|
var ops []InstrHash
|
|
for {
|
|
switch {
|
|
case v.HasFailed():
|
|
// Should be caught and reported already by the v.Step(),
|
|
// but we're checking here anyway just in case.
|
|
return ops, errors.New("VM has failed")
|
|
case v.HasHalted(), v.AtBreakpoint():
|
|
// Normal exit from this loop.
|
|
return ops, nil
|
|
case v.State() == vmstate.None:
|
|
nStr, curInstr := v.Context().NextInstr()
|
|
ops = append(ops, InstrHash{
|
|
Offset: nStr,
|
|
Instruction: curInstr,
|
|
ScriptHash: v.Context().ScriptHash(),
|
|
})
|
|
if err := v.Step(); err != nil {
|
|
return ops, err
|
|
}
|
|
default:
|
|
return ops, errors.New("unknown state")
|
|
}
|
|
}
|
|
}
|