forked from TrueCloudLab/neoneo-go
Merge pull request #267 from dauTT/dauTT/vm-crypto-opcode-194
VM: Implement SHA1, SHA256, HASH160, HASH256 opcode, closes #268. Implemented 1) SHA1 2) SHA256 3) HASH160 4) HASH256
This commit is contained in:
commit
cdb92ebaa2
3 changed files with 211 additions and 0 deletions
|
@ -5,6 +5,10 @@ import "github.com/CityOfZion/neo-go/pkg/vm/stack"
|
|||
type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error)
|
||||
|
||||
var opFunc = map[stack.Instruction]stackInfo{
|
||||
stack.HASH256: HASH256,
|
||||
stack.HASH160: HASH160,
|
||||
stack.SHA256: SHA256,
|
||||
stack.SHA1: SHA1,
|
||||
stack.XOR: Xor,
|
||||
stack.OR: Or,
|
||||
stack.AND: And,
|
||||
|
|
106
pkg/vm/vmopscrypto.go
Normal file
106
pkg/vm/vmopscrypto.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/stack"
|
||||
)
|
||||
|
||||
// SHA1 pops an item off of the stack and
|
||||
// pushes a bytearray onto the stack whose value
|
||||
// is obtained by applying the sha1 algorithm to
|
||||
// the corresponding bytearray representation of the item.
|
||||
// Returns an error if the Pop method cannot be execute or
|
||||
// the popped item does not have a concrete bytearray implementation.
|
||||
func SHA1(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||
|
||||
ba, err := ctx.Estack.PopByteArray()
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
alg := sha1.New()
|
||||
alg.Write(ba.Value())
|
||||
hash := alg.Sum(nil)
|
||||
res := stack.NewByteArray(hash)
|
||||
|
||||
ctx.Estack.Push(res)
|
||||
|
||||
return NONE, nil
|
||||
}
|
||||
|
||||
// SHA256 pops an item off of the stack and
|
||||
// pushes a bytearray onto the stack whose value
|
||||
// is obtained by applying the Sha256 algorithm to
|
||||
// the corresponding bytearray representation of the item.
|
||||
// Returns an error if the Pop method cannot be execute or
|
||||
// the popped item does not have a concrete bytearray implementation.
|
||||
func SHA256(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||
|
||||
ba, err := ctx.Estack.PopByteArray()
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
hash, err := hash.Sha256(ba.Value())
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
res := stack.NewByteArray(hash.Bytes())
|
||||
|
||||
ctx.Estack.Push(res)
|
||||
|
||||
return NONE, nil
|
||||
}
|
||||
|
||||
// HASH160 pops an item off of the stack and
|
||||
// pushes a bytearray onto the stack whose value
|
||||
// is obtained by applying the Hash160 algorithm to
|
||||
// the corresponding bytearray representation of the item.
|
||||
// Returns an error if the Pop method cannot be execute or
|
||||
// the popped item does not have a concrete bytearray implementation.
|
||||
func HASH160(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||
|
||||
ba, err := ctx.Estack.PopByteArray()
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
hash, err := hash.Hash160(ba.Value())
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
res := stack.NewByteArray(hash.Bytes())
|
||||
|
||||
ctx.Estack.Push(res)
|
||||
|
||||
return NONE, nil
|
||||
}
|
||||
|
||||
// HASH256 pops an item off of the stack and
|
||||
// pushes a bytearray onto the stack whose value
|
||||
// is obtained by applying the Hash256 algorithm to
|
||||
// the corresponding bytearray representation of the item.
|
||||
// Returns an error if the Pop method cannot be execute or
|
||||
// the popped item does not have a concrete bytearray implementation.
|
||||
func HASH256(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||
|
||||
ba, err := ctx.Estack.PopByteArray()
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
hash, err := hash.DoubleSha256(ba.Value())
|
||||
if err != nil {
|
||||
return FAULT, err
|
||||
}
|
||||
|
||||
res := stack.NewByteArray(hash.Bytes())
|
||||
|
||||
ctx.Estack.Push(res)
|
||||
|
||||
return NONE, nil
|
||||
}
|
101
pkg/vm/vmopscrypto_test.go
Normal file
101
pkg/vm/vmopscrypto_test.go
Normal file
|
@ -0,0 +1,101 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/stack"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSha1Op(t *testing.T) {
|
||||
|
||||
v := VM{}
|
||||
|
||||
ba1 := stack.NewByteArray([]byte("this is test string"))
|
||||
|
||||
ctx := stack.NewContext([]byte{})
|
||||
ctx.Estack.Push(ba1)
|
||||
|
||||
v.executeOp(stack.SHA1, ctx)
|
||||
|
||||
// Stack should have one item
|
||||
assert.Equal(t, 1, ctx.Estack.Len())
|
||||
|
||||
item, err := ctx.Estack.Pop()
|
||||
assert.Nil(t, err)
|
||||
|
||||
ba2, err := item.ByteArray()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "62d40fe74cf301cbfbe55c2679b96352449fb26d", hex.EncodeToString(ba2.Value()))
|
||||
}
|
||||
|
||||
func TestSha256Op(t *testing.T) {
|
||||
|
||||
v := VM{}
|
||||
|
||||
ba1 := stack.NewByteArray([]byte("this is test string"))
|
||||
|
||||
ctx := stack.NewContext([]byte{})
|
||||
ctx.Estack.Push(ba1)
|
||||
|
||||
v.executeOp(stack.SHA256, ctx)
|
||||
|
||||
// Stack should have one item
|
||||
assert.Equal(t, 1, ctx.Estack.Len())
|
||||
|
||||
item, err := ctx.Estack.Pop()
|
||||
assert.Nil(t, err)
|
||||
|
||||
ba2, err := item.ByteArray()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "8e76c5b9e6be2559bedccbd0ff104ebe02358ba463a44a68e96caf55f9400de5", hex.EncodeToString(ba2.Value()))
|
||||
}
|
||||
|
||||
func TestHash160Op(t *testing.T) {
|
||||
|
||||
v := VM{}
|
||||
|
||||
ba1 := stack.NewByteArray([]byte("this is test string"))
|
||||
|
||||
ctx := stack.NewContext([]byte{})
|
||||
ctx.Estack.Push(ba1)
|
||||
|
||||
v.executeOp(stack.HASH160, ctx)
|
||||
|
||||
// Stack should have one item
|
||||
assert.Equal(t, 1, ctx.Estack.Len())
|
||||
|
||||
item, err := ctx.Estack.Pop()
|
||||
assert.Nil(t, err)
|
||||
|
||||
ba2, err := item.ByteArray()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "e9c052b05a762ca9961a975db52e5417d99d958c", hex.EncodeToString(ba2.Value()))
|
||||
}
|
||||
|
||||
func TestHash256Op(t *testing.T) {
|
||||
|
||||
v := VM{}
|
||||
|
||||
ba1 := stack.NewByteArray([]byte("this is test string"))
|
||||
|
||||
ctx := stack.NewContext([]byte{})
|
||||
ctx.Estack.Push(ba1)
|
||||
|
||||
v.executeOp(stack.HASH256, ctx)
|
||||
|
||||
// Stack should have one item
|
||||
assert.Equal(t, 1, ctx.Estack.Len())
|
||||
|
||||
item, err := ctx.Estack.Pop()
|
||||
assert.Nil(t, err)
|
||||
|
||||
ba2, err := item.ByteArray()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "90ef790ee2557a3f9a1ba0e6910a9ff0ea75af3767ea7380760d729ac9927a60", hex.EncodeToString(ba2.Value()))
|
||||
}
|
Loading…
Reference in a new issue