OSDN Git Service

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