mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 23:33:37 +00:00
parent
3bbeb2476e
commit
ca9c9be71f
4 changed files with 388 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
|
@ -280,3 +281,39 @@ func (s *Stack) Iter(f func(*Element)) {
|
||||||
f(e)
|
f(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// popSigElements pops keys or signatures from the stack as needed for
|
||||||
|
// CHECKMULTISIG.
|
||||||
|
func (s *Stack) popSigElements() ([][]byte, error) {
|
||||||
|
var num int
|
||||||
|
var elems [][]byte
|
||||||
|
item := s.Pop()
|
||||||
|
if item == nil {
|
||||||
|
return nil, fmt.Errorf("nothing on the stack")
|
||||||
|
}
|
||||||
|
switch item.value.(type) {
|
||||||
|
case *ArrayItem:
|
||||||
|
num = len(item.Array())
|
||||||
|
if num < 1 {
|
||||||
|
return nil, fmt.Errorf("less than one element in the array")
|
||||||
|
}
|
||||||
|
elems = make([][]byte, num)
|
||||||
|
for k, v := range item.Array() {
|
||||||
|
b, ok := v.Value().([]byte)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("bad element %s", v.String())
|
||||||
|
}
|
||||||
|
elems[k] = b
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
num = int(item.BigInt().Int64())
|
||||||
|
if num < 1 || num > s.Len() {
|
||||||
|
return nil, fmt.Errorf("wrong number of elements: %d", num)
|
||||||
|
}
|
||||||
|
elems = make([][]byte, num)
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
elems[i] = s.Pop().Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elems, nil
|
||||||
|
}
|
||||||
|
|
|
@ -217,6 +217,44 @@ func TestSwapElemValues(t *testing.T) {
|
||||||
assert.Equal(t, int64(4), s.Pop().BigInt().Int64())
|
assert.Equal(t, int64(4), s.Pop().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPopSigElements(t *testing.T) {
|
||||||
|
s := NewStack("test")
|
||||||
|
|
||||||
|
_, err := s.popSigElements()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
s.PushVal([]StackItem{})
|
||||||
|
_, err = s.popSigElements()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
s.PushVal([]StackItem{NewBoolItem(false)})
|
||||||
|
_, err = s.popSigElements()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
b1 := []byte("smth")
|
||||||
|
b2 := []byte("strange")
|
||||||
|
s.PushVal([]StackItem{NewByteArrayItem(b1), NewByteArrayItem(b2)})
|
||||||
|
z, err := s.popSigElements()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, z, [][]byte{b1, b2})
|
||||||
|
|
||||||
|
s.PushVal(2)
|
||||||
|
_, err = s.popSigElements()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
s.PushVal(b1)
|
||||||
|
s.PushVal(2)
|
||||||
|
_, err = s.popSigElements()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
s.PushVal(b2)
|
||||||
|
s.PushVal(b1)
|
||||||
|
s.PushVal(2)
|
||||||
|
z, err = s.popSigElements()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, z, [][]byte{b1, b2})
|
||||||
|
}
|
||||||
|
|
||||||
func makeElements(n int) []*Element {
|
func makeElements(n int) []*Element {
|
||||||
elems := make([]*Element, n)
|
elems := make([]*Element, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
|
|
66
pkg/vm/vm.go
66
pkg/vm/vm.go
|
@ -11,6 +11,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,6 +44,8 @@ type VM struct {
|
||||||
|
|
||||||
// Mute all output after execution.
|
// Mute all output after execution.
|
||||||
mute bool
|
mute bool
|
||||||
|
// Hash to verify in CHECKSIG/CHECKMULTISIG.
|
||||||
|
checkhash []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new VM object ready to load .avm bytecode scripts.
|
// New returns a new VM object ready to load .avm bytecode scripts.
|
||||||
|
@ -239,6 +242,12 @@ func (v *VM) HasFailed() bool {
|
||||||
return v.state.HasFlag(faultState)
|
return v.state.HasFlag(faultState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCheckedHash sets checked hash for CHECKSIG and CHECKMULTISIG instructions.
|
||||||
|
func (v *VM) SetCheckedHash(h []byte) {
|
||||||
|
v.checkhash = make([]byte, len(h))
|
||||||
|
copy(v.checkhash, h)
|
||||||
|
}
|
||||||
|
|
||||||
// execute performs an instruction cycle in the VM. Acting on the instruction (opcode).
|
// execute performs an instruction cycle in the VM. Acting on the instruction (opcode).
|
||||||
func (v *VM) execute(ctx *Context, op Instruction) {
|
func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
// Instead of polluting the whole VM logic with error handling, we will recover
|
// Instead of polluting the whole VM logic with error handling, we will recover
|
||||||
|
@ -848,7 +857,62 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
v.state = haltState
|
v.state = haltState
|
||||||
}
|
}
|
||||||
|
|
||||||
case CHECKSIG, VERIFY, CHECKMULTISIG, NEWMAP, HASKEY, KEYS, VALUES:
|
case CHECKSIG, VERIFY:
|
||||||
|
var hashToCheck []byte
|
||||||
|
|
||||||
|
keyb := v.estack.Pop().Bytes()
|
||||||
|
signature := v.estack.Pop().Bytes()
|
||||||
|
if op == CHECKSIG {
|
||||||
|
if v.checkhash == nil {
|
||||||
|
panic("VM is not set up properly for signature checks")
|
||||||
|
}
|
||||||
|
hashToCheck = v.checkhash
|
||||||
|
} else { // VERIFY
|
||||||
|
msg := v.estack.Pop().Bytes()
|
||||||
|
hashToCheck = hash.Sha256(msg).Bytes()
|
||||||
|
}
|
||||||
|
pkey := &keys.PublicKey{}
|
||||||
|
err := pkey.DecodeBytes(keyb)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
res := pkey.Verify(signature, hashToCheck)
|
||||||
|
v.estack.PushVal(res)
|
||||||
|
|
||||||
|
case CHECKMULTISIG:
|
||||||
|
pkeys, err := v.estack.popSigElements()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("wrong parameters: %s", err.Error()))
|
||||||
|
}
|
||||||
|
sigs, err := v.estack.popSigElements()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("wrong parameters: %s", err.Error()))
|
||||||
|
}
|
||||||
|
if len(pkeys) < len(sigs) {
|
||||||
|
panic("more signatures than there are keys")
|
||||||
|
}
|
||||||
|
if v.checkhash == nil {
|
||||||
|
panic("VM is not set up properly for signature checks")
|
||||||
|
}
|
||||||
|
sigok := true
|
||||||
|
j := 0
|
||||||
|
for i := 0; sigok && i < len(pkeys) && j < len(sigs); {
|
||||||
|
pkey := &keys.PublicKey{}
|
||||||
|
err := pkey.DecodeBytes(pkeys[j])
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
if pkey.Verify(sigs[i], v.checkhash) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
if len(pkeys)-i > len(sigs)-j {
|
||||||
|
sigok = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.estack.PushVal(sigok)
|
||||||
|
|
||||||
|
case NEWMAP, HASKEY, KEYS, VALUES:
|
||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
|
|
||||||
// Cryptographic operations.
|
// Cryptographic operations.
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -1488,6 +1490,252 @@ func TestREMOVEGood(t *testing.T) {
|
||||||
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCHECKSIGNoArgs(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKSIG)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKSIGOneArg(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKSIG)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKSIGNoSigLoaded(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKSIG)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := "NEO - An Open Network For Smart Economy"
|
||||||
|
sig, err := pk.Sign([]byte(msg))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(sig)
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKSIGBadKey(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKSIG)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig, err := pk.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()[:4]
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal(sig)
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKSIGWrongSig(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKSIG)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig, err := pk.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal(util.ArrayReverse(sig))
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.HasFailed())
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKSIGGood(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKSIG)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig, err := pk.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal(sig)
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.HasFailed())
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVERIFYGood(t *testing.T) {
|
||||||
|
prog := makeProgram(VERIFY)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig, err := pk.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(msg)
|
||||||
|
vm.estack.PushVal(sig)
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.HasFailed())
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVERIFYBad(t *testing.T) {
|
||||||
|
prog := makeProgram(VERIFY)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig, err := pk.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(util.ArrayReverse(msg))
|
||||||
|
vm.estack.PushVal(sig)
|
||||||
|
vm.estack.PushVal(pbytes)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.HasFailed())
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGNoArgs(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGOneArg(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
vm := load(prog)
|
||||||
|
pbytes := pk.PublicKey().Bytes()
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(pbytes)})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGNotEnoughKeys(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
pk1, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pk2, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig1, err := pk1.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
sig2, err := pk2.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes1 := pk1.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(sig1), NewByteArrayItem(sig2)})
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(pbytes1)})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGNoHash(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
pk1, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pk2, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig1, err := pk1.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
sig2, err := pk2.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes1 := pk1.PublicKey().Bytes()
|
||||||
|
pbytes2 := pk2.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(sig1), NewByteArrayItem(sig2)})
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(pbytes1), NewByteArrayItem(pbytes2)})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGBadKey(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
pk1, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pk2, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig1, err := pk1.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
sig2, err := pk2.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes1 := pk1.PublicKey().Bytes()
|
||||||
|
pbytes2 := pk2.PublicKey().Bytes()[:4]
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(sig1), NewByteArrayItem(sig2)})
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(pbytes1), NewByteArrayItem(pbytes2)})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.HasFailed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGBadSig(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
pk1, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pk2, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig1, err := pk1.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
sig2, err := pk2.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes1 := pk1.PublicKey().Bytes()
|
||||||
|
pbytes2 := pk2.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(util.ArrayReverse(sig1)), NewByteArrayItem(sig2)})
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(pbytes1), NewByteArrayItem(pbytes2)})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.HasFailed())
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCHECKMULTISIGGood(t *testing.T) {
|
||||||
|
prog := makeProgram(CHECKMULTISIG)
|
||||||
|
pk1, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pk2, err := keys.NewPrivateKey()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
msg := []byte("NEO - An Open Network For Smart Economy")
|
||||||
|
sig1, err := pk1.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
sig2, err := pk2.Sign(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
pbytes1 := pk1.PublicKey().Bytes()
|
||||||
|
pbytes2 := pk2.PublicKey().Bytes()
|
||||||
|
vm := load(prog)
|
||||||
|
vm.SetCheckedHash(hash.Sha256(msg).Bytes())
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(sig1), NewByteArrayItem(sig2)})
|
||||||
|
vm.estack.PushVal([]StackItem{NewByteArrayItem(pbytes1), NewByteArrayItem(pbytes2)})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.HasFailed())
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
||||||
|
}
|
||||||
|
|
||||||
func makeProgram(opcodes ...Instruction) []byte {
|
func makeProgram(opcodes ...Instruction) []byte {
|
||||||
prog := make([]byte, len(opcodes)+1) // RET
|
prog := make([]byte, len(opcodes)+1) // RET
|
||||||
for i := 0; i < len(opcodes); i++ {
|
for i := 0; i < len(opcodes); i++ {
|
||||||
|
|
Loading…
Reference in a new issue