secp256k1: add support for resource constrained environments (TinyGo)
Some checks failed
Build and Test / Go CI (1.21) (push) Has been cancelled
Build and Test / Go CI (1.22) (push) Has been cancelled

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.
This commit is contained in:
SeedHammer 2024-03-16 19:24:17 +00:00
parent c6322d513a
commit 0d633fcd00
No known key found for this signature in database
4 changed files with 60 additions and 2 deletions

View File

@ -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.

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
@ -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
}
}
}
@ -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,