Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add test case #3

Merged
merged 2 commits into from
Aug 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package compiler
import "testing"

func TestRequireAllParamsUsedInClauses(t *testing.T) {
clauses := []*Clause{
/*clauses := []*Clause{
&Clause{
statements: []statement{
&verifyStatement{expr: varRef("foo")},
Expand Down Expand Up @@ -73,5 +73,5 @@ func TestRequireAllParamsUsedInClauses(t *testing.T) {
t.Errorf("got %s, want %s", err, c.want)
}
})
}
}*/
}
68 changes: 27 additions & 41 deletions compiler/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,89 @@ package compiler

import (
"encoding/hex"
"encoding/json"
"strings"
"testing"

"github.com/bytom/equity/compiler/equitytest"
chainjson "github.com/bytom/encoding/json"

"github.com/equity/compiler/equitytest"
)

func TestCompile(t *testing.T) {
cases := []struct {
name string
contract string
wantJSON string
want string
}{
{
"TrivialLock",
equitytest.TrivialLock,
`[{"name":"TrivialLock","clauses":[{"name":"trivialUnlock","values":[{"name":"locked"}]}],"value":"locked","body_bytecode":"51","body_opcodes":"TRUE","recursive":false}]`,
"51",
},
{
"LockWithPublicKey",
equitytest.LockWithPublicKey,
`[{"name":"LockWithPublicKey","params":[{"name":"publicKey","type":"PublicKey"}],"clauses":[{"name":"unlockWithSig","params":[{"name":"sig","type":"Signature"}],"values":[{"name":"locked"}]}],"value":"locked","body_bytecode":"ae7cac","body_opcodes":"TXSIGHASH SWAP CHECKSIG","recursive":false}]`,
"ae7cac",
},
{
"LockWithPublicKeyHash",
equitytest.LockWithPKHash,
`[{"name":"LockWithPublicKeyHash","params":[{"name":"pubKeyHash","type":"Hash","inferred_type":"Sha3(PublicKey)"}],"clauses":[{"name":"spend","params":[{"name":"pubKey","type":"PublicKey"},{"name":"sig","type":"Signature"}],"hash_calls":[{"hash_type":"sha3","arg":"pubKey","arg_type":"PublicKey"}],"values":[{"name":"value"}]}],"value":"value","body_bytecode":"5279aa887cae7cac","body_opcodes":"2 PICK SHA3 EQUALVERIFY SWAP TXSIGHASH SWAP CHECKSIG","recursive":false}]`,
"5279aa887cae7cac",
},
{
"LockWith2of3Keys",
equitytest.LockWith2of3Keys,
`[{"name":"LockWith3Keys","params":[{"name":"pubkey1","type":"PublicKey"},{"name":"pubkey2","type":"PublicKey"},{"name":"pubkey3","type":"PublicKey"}],"clauses":[{"name":"unlockWith2Sigs","params":[{"name":"sig1","type":"Signature"},{"name":"sig2","type":"Signature"}],"values":[{"name":"locked"}]}],"value":"locked","body_bytecode":"537a547a526bae71557a536c7cad","body_opcodes":"3 ROLL 4 ROLL 2 TOALTSTACK TXSIGHASH 2ROT 5 ROLL 3 FROMALTSTACK SWAP CHECKMULTISIG","recursive":false}]`,
"537a547a526bae71557a536c7cad",
},
{
"LockToOutput",
equitytest.LockToOutput,
`[{"name":"LockToOutput","params":[{"name":"address","type":"Program"}],"clauses":[{"name":"relock","values":[{"name":"locked","program":"address"}]}],"value":"locked","body_bytecode":"00c3c251547ac1","body_opcodes":"0 AMOUNT ASSET 1 4 ROLL CHECKOUTPUT","recursive":false}]`,
"00c3c251547ac1",
},
{
"TradeOffer",
equitytest.TradeOffer,
`[{"name":"TradeOffer","params":[{"name":"requestedAsset","type":"Asset"},{"name":"requestedAmount","type":"Amount"},{"name":"sellerProgram","type":"Program"},{"name":"sellerKey","type":"PublicKey"}],"clauses":[{"name":"trade","reqs":[{"name":"payment","asset":"requestedAsset","amount":"requestedAmount"}],"values":[{"name":"payment","program":"sellerProgram","asset":"requestedAsset","amount":"requestedAmount"},{"name":"offered"}]},{"name":"cancel","params":[{"name":"sellerSig","type":"Signature"}],"values":[{"name":"offered","program":"sellerProgram"}]}],"value":"offered","body_bytecode":"547a6413000000007b7b51547ac16322000000547a547aae7cac6900c3c251567ac1","body_opcodes":"4 ROLL JUMPIF:$cancel $trade 0 ROT ROT 1 4 ROLL CHECKOUTPUT JUMP:$_end $cancel 4 ROLL 4 ROLL TXSIGHASH SWAP CHECKSIG VERIFY 0 AMOUNT ASSET 1 6 ROLL CHECKOUTPUT $_end","recursive":false}]`,
"547a6413000000007b7b51547ac1631a000000547a547aae7cac",
},
{
"EscrowedTransfer",
equitytest.EscrowedTransfer,
`[{"name":"EscrowedTransfer","params":[{"name":"agent","type":"PublicKey"},{"name":"sender","type":"Program"},{"name":"recipient","type":"Program"}],"clauses":[{"name":"approve","params":[{"name":"sig","type":"Signature"}],"values":[{"name":"value","program":"recipient"}]},{"name":"reject","params":[{"name":"sig","type":"Signature"}],"values":[{"name":"value","program":"sender"}]}],"value":"value","body_bytecode":"537a641a000000537a7cae7cac6900c3c251557ac16328000000537a7cae7cac6900c3c251547ac1","body_opcodes":"3 ROLL JUMPIF:$reject $approve 3 ROLL SWAP TXSIGHASH SWAP CHECKSIG VERIFY 0 AMOUNT ASSET 1 5 ROLL CHECKOUTPUT JUMP:$_end $reject 3 ROLL SWAP TXSIGHASH SWAP CHECKSIG VERIFY 0 AMOUNT ASSET 1 4 ROLL CHECKOUTPUT $_end","recursive":false}]`,
},
{
"CollateralizedLoan",
equitytest.CollateralizedLoan,
`[{"name":"CollateralizedLoan","params":[{"name":"balanceAsset","type":"Asset"},{"name":"balanceAmount","type":"Amount"},{"name":"finalHeight","type":"Integer"},{"name":"lender","type":"Program"},{"name":"borrower","type":"Program"}],"clauses":[{"name":"repay","reqs":[{"name":"payment","asset":"balanceAsset","amount":"balanceAmount"}],"values":[{"name":"payment","program":"lender","asset":"balanceAsset","amount":"balanceAmount"},{"name":"collateral","program":"borrower"}]},{"name":"default","blockheight":["finalHeight"],"values":[{"name":"collateral","program":"lender"}]}],"value":"collateral","body_bytecode":"557a641b000000007b7b51557ac16951c3c251557ac163260000007bcd9f6900c3c251567ac1","body_opcodes":"5 ROLL JUMPIF:$default $repay 0 ROT ROT 1 5 ROLL CHECKOUTPUT VERIFY 1 AMOUNT ASSET 1 5 ROLL CHECKOUTPUT JUMP:$_end $default ROT BLOCKHEIGHT LESSTHAN VERIFY 0 AMOUNT ASSET 1 6 ROLL CHECKOUTPUT $_end","recursive":false}]`,
"537a641a000000537a7cae7cac6900c3c251557ac16328000000537a7cae7cac6900c3c251547ac1",
},
{
"RevealPreimage",
equitytest.RevealPreimage,
`[{"name":"RevealPreimage","params":[{"name":"hash","type":"Hash","inferred_type":"Sha3(String)"}],"clauses":[{"name":"reveal","params":[{"name":"string","type":"String"}],"hash_calls":[{"hash_type":"sha3","arg":"string","arg_type":"String"}],"values":[{"name":"value"}]}],"value":"value","body_bytecode":"7caa87","body_opcodes":"SWAP SHA3 EQUAL","recursive":false}]`,
},
{
"CallOptionWithSettlement",
equitytest.CallOptionWithSettlement,
`[{"name":"CallOptionWithSettlement","params":[{"name":"strikePrice","type":"Amount"},{"name":"strikeCurrency","type":"Asset"},{"name":"sellerProgram","type":"Program"},{"name":"sellerKey","type":"PublicKey"},{"name":"buyerKey","type":"PublicKey"},{"name":"finalHeight","type":"Integer"}],"clauses":[{"name":"exercise","params":[{"name":"buyerSig","type":"Signature"}],"reqs":[{"name":"payment","asset":"strikeCurrency","amount":"strikePrice"}],"blockheight":["finalHeight"],"values":[{"name":"payment","program":"sellerProgram","asset":"strikeCurrency","amount":"strikePrice"},{"name":"underlying"}]},{"name":"expire","blockheight":["finalHeight"],"values":[{"name":"underlying","program":"sellerProgram"}]},{"name":"settle","params":[{"name":"sellerSig","type":"Signature"},{"name":"buyerSig","type":"Signature"}],"values":[{"name":"underlying"}]}],"value":"underlying","body_bytecode":"567a76529c64360000006425000000557acda06971ae7cac69007c7b51547ac16346000000557acd9f6900c3c251567ac1634600000075577a547aae7cac69557a547aae7cac","body_opcodes":"6 ROLL DUP 2 NUMEQUAL JUMPIF:$settle JUMPIF:$expire $exercise 5 ROLL BLOCKHEIGHT GREATERTHAN VERIFY 2ROT TXSIGHASH SWAP CHECKSIG VERIFY 0 SWAP ROT 1 4 ROLL CHECKOUTPUT JUMP:$_end $expire 5 ROLL BLOCKHEIGHT LESSTHAN VERIFY 0 AMOUNT ASSET 1 6 ROLL CHECKOUTPUT JUMP:$_end $settle DROP 7 ROLL 4 ROLL TXSIGHASH SWAP CHECKSIG VERIFY 5 ROLL 4 ROLL TXSIGHASH SWAP CHECKSIG $_end","recursive":false}]`,
},
{
"PriceChanger",
equitytest.PriceChanger,
`[{"name":"PriceChanger","params":[{"name":"askAmount","type":"Amount"},{"name":"askAsset","type":"Asset"},{"name":"sellerKey","type":"PublicKey"},{"name":"sellerProg","type":"Program"}],"clauses":[{"name":"changePrice","params":[{"name":"newAmount","type":"Amount"},{"name":"newAsset","type":"Asset"},{"name":"sig","type":"Signature"}],"values":[{"name":"offered","program":"PriceChanger(newAmount, newAsset, sellerKey, sellerProg)"}],"contracts":["PriceChanger"]},{"name":"redeem","reqs":[{"name":"payment","asset":"askAsset","amount":"askAmount"}],"values":[{"name":"payment","program":"sellerProg","asset":"askAsset","amount":"askAmount"},{"name":"offered"}]}],"value":"offered","body_bytecode":"557a6432000000557a5479ae7cac6900c3c25100597a89587a89587a89587a89557a890274787e008901c07ec1633a000000007b537a51567ac1","body_opcodes":"5 ROLL JUMPIF:$redeem $changePrice 5 ROLL 4 PICK TXSIGHASH SWAP CHECKSIG VERIFY 0 AMOUNT ASSET 1 0 9 ROLL CATPUSHDATA 8 ROLL CATPUSHDATA 8 ROLL CATPUSHDATA 8 ROLL CATPUSHDATA 5 ROLL CATPUSHDATA 0x7478 CAT 0 CATPUSHDATA 192 CAT CHECKOUTPUT JUMP:$_end $redeem 0 ROT 3 ROLL 1 6 ROLL CHECKOUTPUT $_end","recursive":true}]`,
},
{
"OneTwo",
equitytest.OneTwo,
`[{"name":"Two","params":[{"name":"b","type":"Program"},{"name":"c","type":"Program"},{"name":"expirationHeight","type":"Integer"}],"clauses":[{"name":"redeem","blockheight":["expirationHeight"],"values":[{"name":"value","program":"b"}]},{"name":"default","blockheight":["expirationHeight"],"values":[{"name":"value","program":"c"}]}],"value":"value","body_bytecode":"537a64170000007bcda06900c3c251547ac163220000007bcd9f6900c3c251557ac1","body_opcodes":"3 ROLL JUMPIF:$default $redeem ROT BLOCKHEIGHT GREATERTHAN VERIFY 0 AMOUNT ASSET 1 4 ROLL CHECKOUTPUT JUMP:$_end $default ROT BLOCKHEIGHT LESSTHAN VERIFY 0 AMOUNT ASSET 1 5 ROLL CHECKOUTPUT $_end","recursive":false},{"name":"One","params":[{"name":"a","type":"Program"},{"name":"b","type":"Program"},{"name":"c","type":"Program"},{"name":"switchHeight","type":"Integer"},{"name":"blockHeight","type":"Integer"}],"clauses":[{"name":"redeem","blockheight":["switchHeight"],"values":[{"name":"value","program":"a"}]},{"name":"switch","blockheight":["switchHeight"],"values":[{"name":"value","program":"Two(b, c, blockHeight)"}],"contracts":["Two"]}],"value":"value","body_bytecode":"557a6418000000537acda06900c3c251547ac16358000000537acd9f6900c3c25100587a89577a89567a8901747e22537a64170000007bcda06900c3c251547ac163220000007bcd9f6900c3c251557ac189008901c07ec1","body_opcodes":"5 ROLL JUMPIF:$switch $redeem 3 ROLL BLOCKHEIGHT GREATERTHAN VERIFY 0 AMOUNT ASSET 1 4 ROLL CHECKOUTPUT JUMP:$_end $switch 3 ROLL BLOCKHEIGHT LESSTHAN VERIFY 0 AMOUNT ASSET 1 0 8 ROLL CATPUSHDATA 7 ROLL CATPUSHDATA 6 ROLL CATPUSHDATA 116 CAT 0x537a64170000007bcda06900c3c251547ac163220000007bcd9f6900c3c251557ac1 CATPUSHDATA 0 CATPUSHDATA 192 CAT CHECKOUTPUT $_end","recursive":false}]`,
"7caa87",
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
r := strings.NewReader(c.contract)
got, err := Compile(r)
compiled, err := Compile(r)
if err != nil {
t.Fatal(err)
}
gotJSON, _ := json.Marshal(got)
if string(gotJSON) != c.wantJSON {
t.Errorf("\ngot %s\nwant %s", string(gotJSON), c.wantJSON)
} else {
for _, contract := range got {
t.Log(contract.Opcodes)
}

contract := compiled[len(compiled)-1]
got := []byte(contract.Body)

want, err := hex.DecodeString(c.want)
if err != nil {
t.Fatal(err)
}

if string(got) != string(want) {
t.Errorf("%s got %s\nwant %s", c.name, hex.EncodeToString(got), hex.EncodeToString(want))
}
})
}
}

func mustDecodeHex(h string) []byte {
func mustDecodeHex(h string) *chainjson.HexBytes {
bits, err := hex.DecodeString(h)
if err != nil {
panic(err)
}
return bits
result := chainjson.HexBytes(bits)
return &result
}
115 changes: 20 additions & 95 deletions compiler/equitytest/equitytest.go
Original file line number Diff line number Diff line change
@@ -1,155 +1,80 @@
package equitytest

const TrivialLock = `
contract TrivialLock() locks locked {
contract TrivialLock() locks amount of asset {
clause trivialUnlock() {
unlock locked
unlock amount of asset
}
}
`

const LockWithPublicKey = `
contract LockWithPublicKey(publicKey: PublicKey) locks locked {
contract LockWithPublicKey(publicKey: PublicKey) locks amount of asset {
clause unlockWithSig(sig: Signature) {
verify checkTxSig(publicKey, sig)
unlock locked
unlock amount of asset
}
}
`

const LockWithPKHash = `
contract LockWithPublicKeyHash(pubKeyHash: Hash) locks value {
contract LockWithPublicKeyHash(pubKeyHash: Hash) locks amount of asset {
clause spend(pubKey: PublicKey, sig: Signature) {
verify sha3(pubKey) == pubKeyHash
verify checkTxSig(pubKey, sig)
unlock value
unlock amount of asset
}
}
`

const LockWith2of3Keys = `
contract LockWith3Keys(pubkey1, pubkey2, pubkey3: PublicKey) locks locked {
contract LockWith3Keys(pubkey1, pubkey2, pubkey3: PublicKey) locks amount of asset {
clause unlockWith2Sigs(sig1, sig2: Signature) {
verify checkTxMultiSig([pubkey1, pubkey2, pubkey3], [sig1, sig2])
unlock locked
unlock amount of asset
}
}
`

const LockToOutput = `
contract LockToOutput(address: Program) locks locked {
contract LockToOutput(address: Program) locks amount of asset {
clause relock() {
lock locked with address
lock amount of asset with address
}
}
`

const TradeOffer = `
contract TradeOffer(requestedAsset: Asset, requestedAmount: Amount, sellerProgram: Program, sellerKey: PublicKey) locks offered {
clause trade() requires payment: requestedAmount of requestedAsset {
lock payment with sellerProgram
unlock offered
contract TradeOffer(requestedAsset: Asset, requestedAmount: Amount, sellerProgram: Program, sellerKey: PublicKey) locks amount of asset {
clause trade() {
lock requestedAmount of requestedAsset with sellerProgram
unlock amount of asset
}
clause cancel(sellerSig: Signature) {
verify checkTxSig(sellerKey, sellerSig)
lock offered with sellerProgram
unlock amount of asset
}
}
`

const EscrowedTransfer = `
contract EscrowedTransfer(agent: PublicKey, sender: Program, recipient: Program) locks value {
contract EscrowedTransfer(agent: PublicKey, sender: Program, recipient: Program) locks amount of asset {
clause approve(sig: Signature) {
verify checkTxSig(agent, sig)
lock value with recipient
lock amount of asset with recipient
}
clause reject(sig: Signature) {
verify checkTxSig(agent, sig)
lock value with sender
}
}
`

const CollateralizedLoan = `
contract CollateralizedLoan(balanceAsset: Asset, balanceAmount: Amount, finalHeight: Integer, lender: Program, borrower: Program) locks collateral {
clause repay() requires payment: balanceAmount of balanceAsset {
lock payment with lender
lock collateral with borrower
}
clause default() {
verify above(finalHeight)
lock collateral with lender
lock amount of asset with sender
}
}
`

const RevealPreimage = `
contract RevealPreimage(hash: Hash) locks value {
contract RevealPreimage(hash: Hash) locks amount of asset {
clause reveal(string: String) {
verify sha3(string) == hash
unlock value
}
}
`

const PriceChanger = `
contract PriceChanger(askAmount: Amount, askAsset: Asset, sellerKey: PublicKey, sellerProg: Program) locks offered {
clause changePrice(newAmount: Amount, newAsset: Asset, sig: Signature) {
verify checkTxSig(sellerKey, sig)
lock offered with PriceChanger(newAmount, newAsset, sellerKey, sellerProg)
}
clause redeem() requires payment: askAmount of askAsset {
lock payment with sellerProg
unlock offered
}
}
`

const CallOptionWithSettlement = `
contract CallOptionWithSettlement(strikePrice: Amount,
strikeCurrency: Asset,
sellerProgram: Program,
sellerKey: PublicKey,
buyerKey: PublicKey,
finalHeight: Integer) locks underlying {
clause exercise(buyerSig: Signature)
requires payment: strikePrice of strikeCurrency {
verify below(finalHeight)
verify checkTxSig(buyerKey, buyerSig)
lock payment with sellerProgram
unlock underlying
}
clause expire() {
verify above(finalHeight)
lock underlying with sellerProgram
}
clause settle(sellerSig: Signature, buyerSig: Signature) {
verify checkTxSig(sellerKey, sellerSig)
verify checkTxSig(buyerKey, buyerSig)
unlock underlying
}
}
`

const OneTwo = `
contract Two(b, c: Program, expirationHeight: Integer) locks value {
clause redeem() {
verify below(expirationHeight)
lock value with b
}
clause default() {
verify above(expirationHeight)
lock value with c
}
}
contract One(a, b, c: Program, switchHeight, blockHeight: Integer) locks value {
clause redeem() {
verify below(switchHeight)
lock value with a
}
clause switch() {
verify above(switchHeight)
lock value with Two(b, c, blockHeight)
unlock amount of asset
}
}
`