Skip to content

Commit

Permalink
secp256k1: add support for resource constrained environments (TinyGo)
Browse files Browse the repository at this point in the history
The pre-computed table for speeding up ScalarBaseMultNonConst is
several hundred kilobytes in the binary and even more when unpacked
into working memory. Special-case ScalarBaseMultNonConst to fall back to
ScalarMultNonConst when the 'tinygo' tag is specified, which is true
when building a Go program with TinyGo.
  • Loading branch information
seedhammer committed Mar 19, 2024
1 parent c6322d5 commit 0d633fc
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 2 deletions.
13 changes: 13 additions & 0 deletions dcrec/secp256k1/curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,19 @@ func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint) {
//
// NOTE: The resulting point will be normalized.
func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) {
scalarBaseMultNonConst(k, result)
}

// scalarBaseMultNonConstSlow computes k*G through ScalarMultNonConst.
func scalarBaseMultNonConstSlow(k *ModNScalar, result *JacobianPoint) {
var G JacobianPoint
bigAffineToJacobian(curveParams.Gx, curveParams.Gy, &G)
ScalarMultNonConst(k, &G, result)
}

// scalarBaseMultNonConstFast computes k*G through the precomputed lookup
// tables.
func scalarBaseMultNonConstFast(k *ModNScalar, result *JacobianPoint) {
bytePoints := s256BytePoints()

// Start with the point at infinity.
Expand Down
14 changes: 14 additions & 0 deletions dcrec/secp256k1/curve_embedded.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2024 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

//go:build tinygo

package secp256k1

// This file contains the variants suitable for
// memory or storage constrained environments.

func scalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) {
scalarBaseMultNonConstSlow(k, result)
}
14 changes: 14 additions & 0 deletions dcrec/secp256k1/curve_precompute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2024 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

//go:build !tinygo

package secp256k1

// This file contains the variants that don't fit in
// memory or storage constrained environments.

func scalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) {
scalarBaseMultNonConstFast(k, result)
}
21 changes: 19 additions & 2 deletions dcrec/secp256k1/curve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ func TestScalarBaseMultJacobian(t *testing.T) {

// Ensure the result matches the expected value in Jacobian coordinates.
var r JacobianPoint
ScalarBaseMultNonConst(k, &r)
scalarBaseMultNonConstFast(k, &r)
if !r.IsStrictlyEqual(&want) {
t.Errorf("%q: wrong result:\ngot: (%s, %s, %s)\nwant: (%s, %s, %s)",
test.name, r.X, r.Y, r.Z, want.X, want.Y, want.Z)
Expand All @@ -579,6 +579,16 @@ func TestScalarBaseMultJacobian(t *testing.T) {
test.name, r.X, r.Y, wantAffine.X, wantAffine.Y)
continue
}

// The slow fallback doesn't return identical Jacobian coordinates,
// but the affine coordinates should match.
scalarBaseMultNonConstSlow(k, &r)
r.ToAffine()
if !r.IsStrictlyEqual(&wantAffine) {
t.Errorf("%q: wrong affine result:\ngot: (%s, %s)\nwant: (%s, %s)",
test.name, r.X, r.Y, wantAffine.X, wantAffine.Y)
continue
}
}
}

Expand Down Expand Up @@ -827,7 +837,14 @@ func TestScalarMultJacobianRandom(t *testing.T) {

// Ensure the point calculated above matches the product of the scalars
// times the base point.
ScalarBaseMultNonConst(product, &result)
scalarBaseMultNonConstFast(product, &result)
if !isSamePoint(&chained, &result) {
t.Fatalf("unexpected result \ngot (%v, %v, %v)\n"+
"want (%v, %v, %v)", chained.X, chained.Y, chained.Z, result.X,
result.Y, result.Z)
}

scalarBaseMultNonConstSlow(product, &result)
if !isSamePoint(&chained, &result) {
t.Fatalf("unexpected result \ngot (%v, %v, %v)\n"+
"want (%v, %v, %v)", chained.X, chained.Y, chained.Z, result.X,
Expand Down

0 comments on commit 0d633fc

Please sign in to comment.