OSDN Git Service

V0.1 pk interface (#58)
[bytom/vapor.git] / protocol / vm / crypto.go
1 package vm
2
3 import (
4         "crypto/sha256"
5         "hash"
6
7         "golang.org/x/crypto/sha3"
8
9         "github.com/vapor/crypto"
10         "github.com/vapor/crypto/ed25519"
11         "github.com/vapor/math/checked"
12 )
13
14 func opSha256(vm *virtualMachine) error {
15         return doHash(vm, sha256.New)
16 }
17
18 func opSha3(vm *virtualMachine) error {
19         return doHash(vm, sha3.New256)
20 }
21
22 func doHash(vm *virtualMachine, hashFactory func() hash.Hash) error {
23         x, err := vm.pop(false)
24         if err != nil {
25                 return err
26         }
27         cost := int64(len(x))
28         if cost < 64 {
29                 cost = 64
30         }
31         err = vm.applyCost(cost)
32         if err != nil {
33                 return err
34         }
35         h := hashFactory()
36         _, err = h.Write(x)
37         if err != nil {
38                 return err
39         }
40         return vm.push(h.Sum(nil), false)
41 }
42
43 func opCheckSig(vm *virtualMachine) error {
44         err := vm.applyCost(1024)
45         if err != nil {
46                 return err
47         }
48         pubkeyBytes, err := vm.pop(true)
49         if err != nil {
50                 return err
51         }
52         msg, err := vm.pop(true)
53         if err != nil {
54                 return err
55         }
56         sig, err := vm.pop(true)
57         if err != nil {
58                 return err
59         }
60         if len(msg) != 32 {
61                 return ErrBadValue
62         }
63         if len(pubkeyBytes) != ed25519.PublicKeySize {
64                 return vm.pushBool(false, true)
65         }
66         return vm.pushBool(ed25519.Verify(ed25519.PublicKey(pubkeyBytes), msg, sig), true)
67 }
68
69 func opCheckMultiSig(vm *virtualMachine) error {
70         numPubkeys, err := vm.popInt64(true)
71         if err != nil {
72                 return err
73         }
74         pubCost, ok := checked.MulInt64(numPubkeys, 1024)
75         if numPubkeys < 0 || !ok {
76                 return ErrBadValue
77         }
78         err = vm.applyCost(pubCost)
79         if err != nil {
80                 return err
81         }
82         numSigs, err := vm.popInt64(true)
83         if err != nil {
84                 return err
85         }
86         if numSigs < 0 || numSigs > numPubkeys || (numPubkeys > 0 && numSigs == 0) {
87                 return ErrBadValue
88         }
89         pubkeyByteses := make([][]byte, 0, numPubkeys)
90         for i := int64(0); i < numPubkeys; i++ {
91                 pubkeyBytes, err := vm.pop(true)
92                 if err != nil {
93                         return err
94                 }
95                 pubkeyByteses = append(pubkeyByteses, pubkeyBytes)
96         }
97         msg, err := vm.pop(true)
98         if err != nil {
99                 return err
100         }
101         if len(msg) != 32 {
102                 return ErrBadValue
103         }
104         sigs := make([][]byte, 0, numSigs)
105         for i := int64(0); i < numSigs; i++ {
106                 sig, err := vm.pop(true)
107                 if err != nil {
108                         return err
109                 }
110                 sigs = append(sigs, sig)
111         }
112
113         pubkeys := make([]ed25519.PublicKey, 0, numPubkeys)
114         for _, p := range pubkeyByteses {
115                 if len(p) != ed25519.PublicKeySize {
116                         return vm.pushBool(false, true)
117                 }
118                 pubkeys = append(pubkeys, ed25519.PublicKey(p))
119         }
120
121         for len(sigs) > 0 && len(pubkeys) > 0 {
122                 if ed25519.Verify(pubkeys[0], msg, sigs[0]) {
123                         sigs = sigs[1:]
124                 }
125                 pubkeys = pubkeys[1:]
126         }
127         return vm.pushBool(len(sigs) == 0, true)
128 }
129
130 func opTxSigHash(vm *virtualMachine) error {
131         err := vm.applyCost(256)
132         if err != nil {
133                 return err
134         }
135         if vm.context.TxSigHash == nil {
136                 return ErrContext
137         }
138         return vm.push(vm.context.TxSigHash(), false)
139 }
140
141 func opHash160(vm *virtualMachine) error {
142         data, err := vm.pop(false)
143         if err != nil {
144                 return err
145         }
146
147         cost := int64(len(data) + 64)
148         if err = vm.applyCost(cost); err != nil {
149                 return err
150         }
151
152         return vm.push(crypto.Ripemd160(data), false)
153 }