OSDN Git Service

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