OSDN Git Service

delete amount checking for unlock statement (#37)
[bytom/equity.git] / compiler / compile_test.go
1 package compiler
2
3 import (
4         "encoding/hex"
5         "strings"
6         "testing"
7 )
8
9 const TrivialLock = `
10 contract TrivialLock() locks amount of asset {
11   clause trivialUnlock() {
12     unlock amount of asset
13   }
14 }
15 `
16
17 const LockWithPublicKey = `
18 contract LockWithPublicKey(publicKey: PublicKey) locks amount of asset {
19   clause unlockWithSig(sig: Signature) {
20     verify checkTxSig(publicKey, sig)
21     unlock amount of asset
22   }
23 }
24 `
25
26 const LockWithPKHash = `
27 contract LockWithPublicKeyHash(pubKeyHash: Hash) locks amount of asset {
28   clause spend(pubKey: PublicKey, sig: Signature) {
29     verify sha3(pubKey) == pubKeyHash
30     verify checkTxSig(pubKey, sig)
31     unlock amount of asset
32   }
33 }
34 `
35
36 const LockWith2of3Keys = `
37 contract LockWith3Keys(pubkey1, pubkey2, pubkey3: PublicKey) locks amount of asset {
38   clause unlockWith2Sigs(sig1, sig2: Signature) {
39     verify checkTxMultiSig([pubkey1, pubkey2, pubkey3], [sig1, sig2])
40     unlock amount of asset
41   }
42 }
43 `
44
45 const LockToOutput = `
46 contract LockToOutput(address: Program) locks amount of asset {
47   clause relock() {
48     lock amount of asset with address
49   }
50 }
51 `
52
53 const TradeOffer = `
54 contract TradeOffer(requestedAsset: Asset, requestedAmount: Amount, sellerProgram: Program, sellerKey: PublicKey) locks amount of asset {
55   clause trade() {
56     lock requestedAmount of requestedAsset with sellerProgram
57     unlock amount of asset
58   }
59   clause cancel(sellerSig: Signature) {
60     verify checkTxSig(sellerKey, sellerSig)
61     unlock amount of asset
62   }
63 }
64 `
65
66 const EscrowedTransfer = `
67 contract EscrowedTransfer(agent: PublicKey, sender: Program, recipient: Program) locks amount of asset {
68   clause approve(sig: Signature) {
69     verify checkTxSig(agent, sig)
70     lock amount of asset with recipient
71   }
72   clause reject(sig: Signature) {
73     verify checkTxSig(agent, sig)
74     lock amount of asset with sender
75   }
76 }
77 `
78
79 const CollateralizedLoan = `
80 contract CollateralizedLoan(balanceAsset: Asset, balanceAmount: Amount, finalHeight: Integer, lender: Program, borrower: Program) locks valueAmount of valueAsset {
81   clause repay() {
82     lock balanceAmount of balanceAsset with lender
83     lock valueAmount of valueAsset with borrower
84   }
85   clause default() {
86     verify above(finalHeight)
87     lock valueAmount of valueAsset with lender
88   }
89 }
90 `
91
92 const RevealPreimage = `
93 contract RevealPreimage(hash: Hash) locks amount of asset {
94   clause reveal(string: String) {
95     verify sha3(string) == hash
96     unlock amount of asset
97   }
98 }
99 `
100
101 const PriceChanger = `
102 contract PriceChanger(askAmount: Amount, askAsset: Asset, sellerKey: PublicKey, sellerProg: Program) locks valueAmount of valueAsset {
103   clause changePrice(newAmount: Amount, newAsset: Asset, sig: Signature) {
104     verify checkTxSig(sellerKey, sig)
105     lock valueAmount of valueAsset with PriceChanger(newAmount, newAsset, sellerKey, sellerProg)
106   }
107   clause redeem() {
108     lock askAmount of askAsset with sellerProg
109     unlock valueAmount of valueAsset
110   }
111 }
112 `
113
114 const CallOptionWithSettlement = `
115 contract CallOptionWithSettlement(strikePrice: Amount,
116                     strikeCurrency: Asset,
117                     sellerProgram: Program,
118                     sellerKey: PublicKey,
119                     buyerKey: PublicKey,
120                     finalHeight: Integer) locks valueAmount of valueAsset {
121   clause exercise(buyerSig: Signature) {
122     verify below(finalHeight)
123     verify checkTxSig(buyerKey, buyerSig)
124     lock strikePrice of strikeCurrency with sellerProgram
125     unlock valueAmount of valueAsset
126   }
127   clause expire() {
128     verify above(finalHeight)
129     lock valueAmount of valueAsset with sellerProgram
130   }
131   clause settle(sellerSig: Signature, buyerSig: Signature) {
132     verify checkTxSig(sellerKey, sellerSig)
133     verify checkTxSig(buyerKey, buyerSig)
134     unlock valueAmount of valueAsset
135   }
136 }
137 `
138
139 const TestDefineVar = `
140 contract TestDefineVar(result: Integer) locks valueAmount of valueAsset {
141   clause LockWithMath(left: Integer, right: Integer) {
142     define calculate: Integer = left + right
143     verify left != calculate
144     verify result == calculate
145     unlock valueAmount of valueAsset
146   }
147 }
148 `
149
150 const TestAssignVar = `
151 contract TestAssignVar(result: Integer) locks valueAmount of valueAsset {
152   clause LockWithMath(first: Integer, second: Integer) {
153     define calculate: Integer = first
154     assign calculate = calculate + second
155     verify result == calculate
156     unlock valueAmount of valueAsset
157   }
158 }
159 `
160
161 const TestSigIf = `
162 contract TestSigIf(a: Integer, count:Integer) locks valueAmount of valueAsset {
163   clause check(b: Integer, c: Integer) {
164     verify b != count
165     if a > b {
166         verify b > c
167     } else {
168         verify a > c
169     }
170     unlock valueAmount of valueAsset
171   }
172 }
173 `
174
175 const TestIfAndMultiClause = `
176 contract TestIfAndMultiClause(a: Integer, cancelKey: PublicKey) locks valueAmount of valueAsset {
177   clause check(b: Integer, c: Integer) {
178     verify b != c
179     if a > b {
180         verify a > c
181     }
182     unlock valueAmount of valueAsset
183   }
184   clause cancel(sellerSig: Signature) {
185     verify checkTxSig(cancelKey, sellerSig)
186     unlock valueAmount of valueAsset
187   }
188 }
189 `
190
191 const TestIfNesting = `
192 contract TestIfNesting(a: Integer, count:Integer) locks valueAmount of valueAsset {
193   clause check(b: Integer, c: Integer, d: Integer) {
194     verify b != count
195     if a > b {
196         if d > c {
197            verify a > d
198         }
199         verify d != b
200     } else {
201         verify a > c
202     }
203     verify c != count
204     unlock valueAmount of valueAsset
205   }
206   clause cancel(e: Integer, f: Integer) {
207     verify a != e
208     if a > f {
209       verify e > count
210     }
211     verify f != count
212     unlock valueAmount of valueAsset
213   }
214 }
215 `
216
217 const TestConstantMath = `
218 contract TestConstantMath(result: Integer, hashByte: Hash, hashStr: Hash, outcome: Boolean) locks valueAmount of valueAsset {
219   clause calculation(left: Integer, right: Integer, boolResult: Boolean) {
220     verify result == left + right + 10
221     verify hashByte == sha3(0x31323330)
222     verify hashStr == sha3('string')
223     verify !outcome
224     verify boolResult && (result == left + 20)
225     unlock valueAmount of valueAsset
226   }
227 }
228 `
229
230 const VerifySignature = `
231 contract VerifySignature(sig1: Sign, sig2: Sign, msgHash: Hash) locks valueAmount of valueAsset {
232   clause check(publicKey1: PublicKey, publicKey2: PublicKey) {
233     verify checkMsgSig(publicKey1, msgHash, sig1)
234     verify checkMsgSig(publicKey2, msgHash, sig2)
235     unlock valueAmount of valueAsset
236   }
237 }
238 `
239
240 func TestCompile(t *testing.T) {
241         cases := []struct {
242                 name     string
243                 contract string
244                 want     string
245         }{
246                 {
247                         "TrivialLock",
248                         TrivialLock,
249                         "51",
250                 },
251                 {
252                         "LockWithPublicKey",
253                         LockWithPublicKey,
254                         "ae7cac",
255                 },
256                 {
257                         "LockWithPublicKeyHash",
258                         LockWithPKHash,
259                         "5279aa887cae7cac",
260                 },
261                 {
262                         "LockWith2of3Keys",
263                         LockWith2of3Keys,
264                         "537a547a526bae71557a536c7cad",
265                 },
266                 {
267                         "LockToOutput",
268                         LockToOutput,
269                         "00c3c251547ac1",
270                 },
271                 {
272                         "TradeOffer",
273                         TradeOffer,
274                         "547a6413000000007b7b51547ac1631a000000547a547aae7cac",
275                 },
276                 {
277                         "EscrowedTransfer",
278                         EscrowedTransfer,
279                         "537a641a000000537a7cae7cac6900c3c251557ac16328000000537a7cae7cac6900c3c251547ac1",
280                 },
281                 {
282                         "CollateralizedLoan",
283                         CollateralizedLoan,
284                         "557a641b000000007b7b51557ac16951c3c251557ac163260000007bcd9f6900c3c251567ac1",
285                 },
286                 {
287                         "RevealPreimage",
288                         RevealPreimage,
289                         "7caa87",
290                 },
291                 {
292                         "PriceChanger",
293                         PriceChanger,
294                         "557a6432000000557a5479ae7cac6900c3c25100597a89587a89587a89587a89557a890274787e008901c07ec1633a000000007b537a51567ac1",
295                 },
296                 {
297                         "CallOptionWithSettlement",
298                         CallOptionWithSettlement,
299                         "567a76529c64360000006425000000557acda06971ae7cac69007c7b51547ac16346000000557acd9f6900c3c251567ac1634600000075577a547aae7cac69557a547aae7cac",
300                 },
301                 {
302                         "TestDefineVar",
303                         TestDefineVar,
304                         "52797b937b7887916987",
305                 },
306                 {
307                         "TestAssignVar",
308                         TestAssignVar,
309                         "7b7b9387",
310                 },
311                 {
312                         "TestSigIf",
313                         TestSigIf,
314                         "53797b879169765379a09161641c00000052795279a0696321000000765279a069",
315                 },
316                 {
317                         "TestIfAndMultiClause",
318                         TestIfAndMultiClause,
319                         "7b641f0000007087916976547aa09161641a000000765379a06963240000007b7bae7cac",
320                 },
321                 {
322                         "TestIfNesting",
323                         TestIfNesting,
324                         "7b644400000054795279879169765579a09161643500000052795479a091616429000000765379a06952795579879169633a000000765479a06953797b8791635c0000007654798791695279a091616459000000527978a0697d8791",
325                 },
326                 {
327                         "TestConstantMath",
328                         TestConstantMath,
329                         "765779577a935a93887c0431323330aa887c06737472696e67aa887c91697b011493879a",
330                 },
331                 {
332                         "VerifySignature",
333                         VerifySignature,
334                         "5279557aac697c7bac",
335                 },
336         }
337
338         for _, c := range cases {
339                 t.Run(c.name, func(t *testing.T) {
340                         r := strings.NewReader(c.contract)
341                         compiled, err := Compile(r)
342                         if err != nil {
343                                 t.Fatal(err)
344                         }
345
346                         contract := compiled[len(compiled)-1]
347                         got := []byte(contract.Body)
348
349                         want, err := hex.DecodeString(c.want)
350                         if err != nil {
351                                 t.Fatal(err)
352                         }
353
354                         if string(got) != string(want) {
355                                 t.Errorf("%s got  %s\nwant %s", c.name, hex.EncodeToString(got), hex.EncodeToString(want))
356                         }
357                 })
358         }
359 }