Skip to content

Commit

Permalink
Add ecdsa
Browse files Browse the repository at this point in the history
  • Loading branch information
algorandskiy authored and pzbitskiy committed Apr 6, 2022
1 parent 289f45b commit a38b87f
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 64 deletions.
10 changes: 10 additions & 0 deletions TealangLexer.l4
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ BUILTINFUNC
| GAID
;

ECDSACURVE
: CURVESECP256K1
;

MAINFUNC
: LOGIC
| APPROVAL
Expand Down Expand Up @@ -318,6 +322,10 @@ BITLEN : 'bitlen' ;
BZERO : 'bzero' ;
GAID : 'gaid' ;

ECDSAVERIFY : 'ecdsa_verify' ;
ECDSADECOMPRESS : 'ecdsa_pk_decompress' ;
ECDSARECOVER : 'ecdsa_pk_recover' ;

BADD : 'badd' ;
BSUB : 'bsub' ;
BDIV : 'bdiv' ;
Expand Down Expand Up @@ -365,6 +373,8 @@ APPADDRESS : 'AppAddress' ;
ITXNBEGIN : 'begin' ;
ITXNEND : 'submit' ;

CURVESECP256K1 : 'Secp256k1';

STRING : EncodingPrefix? '"' StringChar* '"' ;
NUMBER : [0-9]+ ;
IDENT : [a-zA-Z_]+[a-zA-Z0-9_]* ;
Expand Down
3 changes: 3 additions & 0 deletions TealangParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ tupleExpr
| ADDW LEFTPARA ( expr COMMA expr ) RIGHTPARA
| EXPW LEFTPARA ( expr COMMA expr ) RIGHTPARA
| DIVMODW LEFTPARA ( expr COMMA expr COMMA expr COMMA expr ) RIGHTPARA
| ECDSADECOMPRESS LEFTPARA ( ECDSACURVE COMMA expr ) RIGHTPARA
| ECDSARECOVER LEFTPARA ( ECDSACURVE COMMA expr COMMA expr COMMA expr COMMA expr ) RIGHTPARA
| builtinVarTupleExpr
;

Expand All @@ -128,6 +130,7 @@ logStatement
functionCall
: BUILTINFUNC LEFTPARA (expr (COMMA expr)* )? RIGHTPARA # BuiltinFunCall
| IDENT LEFTPARA (expr (COMMA expr)* )? RIGHTPARA # FunCall
| ECDSAVERIFY LEFTPARA ( ECDSACURVE COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr ) RIGHTPARA # EcDsaFunCall
;

builtinVarExpr
Expand Down
5 changes: 4 additions & 1 deletion compiler/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,11 +661,14 @@ func newForStatementNode(ctx *context, parent TreeNodeIf) (node *forStatementNod
return
}

func newFunCallNode(ctx *context, parent TreeNodeIf, name string) (node *funCallNode) {
func newFunCallNode(ctx *context, parent TreeNodeIf, name string, aux ...string) (node *funCallNode) {
node = new(funCallNode)
node.TreeNode = newNode(ctx, parent)
node.nodeName = "fun call"
node.name = name
if len(aux) > 0 {
node.field = aux[0]
}
node.funType = unknownType
return
}
Expand Down
117 changes: 60 additions & 57 deletions compiler/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,66 @@ import (
)

var builtinFun = map[string]bool{
"sha256": true,
"keccak256": true,
"sha512_256": true,
"ed25519verify": true,
"len": true,
"itob": true,
"btoi": true,
"concat": true,
"substring": true,
"substring3": false, // not a tealang builtin but TEAL func
"mulw": true,
"addw": true,
"expw": true,
"divmodw": true,
"exp": true,
"balance": true,
"min_balance": true,
"app_opted_in": true,
"app_local_get": true,
"app_local_get_ex": true,
"app_global_get": true,
"app_global_get_ex": true,
"app_local_put": true, // accounts[x].put
"app_global_put": true, // apps[0].put
"app_local_del": true, // accounts[x].del
"app_global_del": true, // apps[0].del
"asset_holding_get": true,
"app_params_get": true,
"asset_params_get": true,
"assert": true,
"getbit": true,
"getbyte": true,
"setbit": true,
"setbyte": true,
"shl": true,
"shr": true,
"sqrt": true,
"bitlen": true,
"bzero": true,
"badd": true,
"bsub": true,
"bdiv": true,
"bmul": true,
"blt": true,
"bgt": true,
"ble": true,
"bge": true,
"beq": true,
"bne": true,
"bmod": true,
"bor": true,
"band": true,
"bxor": true,
"bnot": true,
"gaid": true,
"gaids": false, // not a tealang builtin but TEAL func
"log": true,
"sha256": true,
"keccak256": true,
"sha512_256": true,
"ed25519verify": true,
"len": true,
"itob": true,
"btoi": true,
"concat": true,
"substring": true,
"substring3": false, // not a tealang builtin but TEAL func
"mulw": true,
"addw": true,
"expw": true,
"divmodw": true,
"exp": true,
"balance": true,
"min_balance": true,
"app_opted_in": true,
"app_local_get": true,
"app_local_get_ex": true,
"app_global_get": true,
"app_global_get_ex": true,
"app_local_put": true, // accounts[x].put
"app_global_put": true, // apps[0].put
"app_local_del": true, // accounts[x].del
"app_global_del": true, // apps[0].del
"asset_holding_get": true,
"app_params_get": true,
"asset_params_get": true,
"assert": true,
"getbit": true,
"getbyte": true,
"setbit": true,
"setbyte": true,
"shl": true,
"shr": true,
"sqrt": true,
"bitlen": true,
"bzero": true,
"badd": true,
"bsub": true,
"bdiv": true,
"bmul": true,
"blt": true,
"bgt": true,
"ble": true,
"bge": true,
"beq": true,
"bne": true,
"bmod": true,
"bor": true,
"band": true,
"bxor": true,
"bnot": true,
"gaid": true,
"gaids": false, // not a tealang builtin but TEAL func
"log": true,
"ecdsa_verify": true,
"ecdsa_pk_decompress": true,
"ecdsa_pk_recover": true,
}

var builtinFunDependantTypes = map[string]int{
Expand Down
48 changes: 46 additions & 2 deletions compiler/codegen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,7 @@ function approval() {
a.Empty(errors)
actual := Codegen(result)

expected := `#pragma version 5
expected := `#pragma version *
intcblock 0 1
bytecblock 0x30
fun_main:
Expand Down Expand Up @@ -1384,7 +1384,7 @@ function logic() {
a.Empty(errors)
actual := Codegen(result)

expected := `#pragma version 5
expected := `#pragma version *
intcblock 0 1
bytecblock 0x4869
fun_main:
Expand All @@ -1396,3 +1396,47 @@ end_main:
`
CompareTEAL(a, expected, actual)
}

func TestCodegenEcdsa(t *testing.T) {
a := require.New(t)
source := `
function logic() {
let res = ecdsa_verify(Secp256k1, "a", "b", "c", "d", "e")
let d1, d2 = ecdsa_pk_decompress(Secp256k1, "a")
d1, d2 = ecdsa_pk_recover(Secp256k1, "a", 1, "b", "c")
return res
}
`
result, errors := Parse(source)
a.NotEmpty(result, errors)
a.Empty(errors)
actual := Codegen(result)

expected := `#pragma version *
intcblock 0 1
*
fun_main:
bytec 0
bytec 1
bytec 2
bytec 3
bytec 4
ecdsa_verify Secp256k1
store 0
bytec 0
ecdsa_pk_decompress Secp256k1
store 1
store 2
bytec 0
intc 1
bytec 1
bytec 2
ecdsa_pk_recover Secp256k1
store 1
store 2
load 0
return
end_main:
`
CompareTEAL(a, expected, actual)
}
35 changes: 31 additions & 4 deletions compiler/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1172,8 +1172,25 @@ func (l *exprListener) EnterFunCall(ctx *gen.FunCallContext) {
l.expr = funCallExprNode
}

func (l *exprListener) funCallEnterImpl(name string, allExpr []gen.IExprContext) (node *funCallNode) {
node = newFunCallNode(l.ctx, l.parent, name)
func (l *exprListener) EnterEcDsaFunCall(ctx *gen.EcDsaFunCallContext) {
name := ctx.ECDSAVERIFY().GetText()
field := ctx.ECDSACURVE().GetText()
exprNode := l.funCallEnterImpl(name, ctx.AllExpr(), field)

err := exprNode.checkBuiltinArgs()
if err != nil {
parser := ctx.GetParser()
token := ctx.ECDSAVERIFY().GetSymbol()
rule := ctx.GetRuleContext()
reportError(err.Error(), parser, token, rule)
return
}

l.expr = exprNode
}

func (l *exprListener) funCallEnterImpl(name string, allExpr []gen.IExprContext, aux ...string) (node *funCallNode) {
node = newFunCallNode(l.ctx, l.parent, name, aux...)
for _, expr := range allExpr {
listener := newExprListener(l.ctx, node)
expr.EnterRule(listener)
Expand All @@ -1192,18 +1209,28 @@ func (l *exprListener) EnterTupleExpr(ctx *gen.TupleExprContext) {
return
}

var field string
var name string
if ctx.MULW() != nil {
name = ctx.MULW().GetText()
} else if ctx.ADDW() != nil {
name = ctx.ADDW().GetText()
} else if ctx.EXPW() != nil {
name = ctx.EXPW().GetText()
} else {
} else if ctx.DIVMODW() != nil {
name = ctx.DIVMODW().GetText()
} else if ctx.ECDSADECOMPRESS() != nil {
name = ctx.ECDSADECOMPRESS().GetText()
field = ctx.ECDSACURVE().GetText()
} else if ctx.ECDSARECOVER() != nil {
name = ctx.ECDSARECOVER().GetText()
field = ctx.ECDSACURVE().GetText()
} else {
token := ctx.GetParser().GetCurrentToken()
reportError("unexpected token", ctx.GetParser(), token, ctx.GetRuleContext())
}

exprNode := l.funCallEnterImpl(name, ctx.AllExpr())
exprNode := l.funCallEnterImpl(name, ctx.AllExpr(), field)

err := exprNode.checkBuiltinArgs()
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ Syntax highlighter for vscode: https://github.com/pzbitskiy/tealang-syntax-highl
if !compileOnly {
op, err = logic.AssembleString(teal)
if err != nil {
for _, err := range op.Errors {
fmt.Println(err)
}
fmt.Println(err.Error())
os.Exit(1)
}
Expand Down

0 comments on commit a38b87f

Please sign in to comment.