github.com/emmansun/gmsm@v0.29.1/sm9/bn256/generate.go (about)

     1  //go:build ignore
     2  
     3  package main
     4  
     5  import (
     6  	"bytes"
     7  	"go/format"
     8  	"io"
     9  	"log"
    10  	"os"
    11  	"os/exec"
    12  )
    13  
    14  // Running this generator requires addchain v0.4.0, which can be installed with
    15  //
    16  //   go install github.com/mmcloughlin/addchain/cmd/addchain@v0.4.0
    17  //
    18  
    19  func generate(template, exp, element string) ([]byte, error) {
    20  	tmplAddchainFileInvert, err := os.CreateTemp("", "addchain-template")
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	defer os.Remove(tmplAddchainFileInvert.Name())
    25  	if _, err := io.WriteString(tmplAddchainFileInvert, template); err != nil {
    26  		return nil, err
    27  	}
    28  	if err := tmplAddchainFileInvert.Close(); err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	f, err := os.CreateTemp("", "addchain-gfp")
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	defer os.Remove(f.Name())
    37  	cmd := exec.Command("addchain", "search", exp)
    38  	cmd.Stderr = os.Stderr
    39  	cmd.Stdout = f
    40  	if err := cmd.Run(); err != nil {
    41  		return nil, err
    42  	}
    43  	if err := f.Close(); err != nil {
    44  		return nil, err
    45  	}
    46  	cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFileInvert.Name(), f.Name())
    47  	cmd.Stderr = os.Stderr
    48  	out, err := cmd.Output()
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	out = bytes.Replace(out, []byte("Element"), []byte(element), -1)
    53  	return format.Source(out)
    54  }
    55  
    56  func writeFile(fileName string, buffers ...[]byte) error {
    57  	log.Printf("Generating %v...", fileName)
    58  	f, err := os.Create(fileName)
    59  	if err != nil {
    60  		log.Fatal(err)
    61  	}
    62  	defer f.Close()
    63  	for _, buffer := range buffers {
    64  		if _, err := f.Write(buffer); err != nil {
    65  			return err
    66  		}
    67  	}
    68  	return nil
    69  }
    70  
    71  func main() {
    72  	out, err := generate(tmplAddchainInvert, "0xb640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457b", "gfP")
    73  	if err != nil {
    74  		log.Fatal(err)
    75  	}
    76  	out1, err := generate(tmplAddchainSqrt, "0x16c80000005474de3ac07569feb1d8e8a43e5269634f5ddb7cadf364fc6a28af", "gfP")
    77  	if err != nil {
    78  		log.Fatal(err)
    79  	}
    80  	if err = writeFile("gfp_invert_sqrt.go", out, out1); err != nil {
    81  		log.Fatal(err)
    82  	}
    83  
    84  	out, err = generate(tmplAddchainExp1, "0x2d90000000a8e9bc7580ead3fd63b1d1487ca4d2c69ebbb6f95be6c9f8d4515f", "gfP2")
    85  	if err != nil {
    86  		log.Fatal(err)
    87  	}
    88  	out1, err = generate(tmplAddchainExp2, "0xb640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457d", "gfP2")
    89  	if err != nil {
    90  		log.Fatal(err)
    91  	}
    92  	out2, err := generate(tmplAddchainExp3, "0x5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be", "gfP2")
    93  	if err != nil {
    94  		log.Fatal(err)
    95  	}
    96  	if err = writeFile("gfp2_sqrt.go", out, out1, out2); err != nil {
    97  		log.Fatal(err)
    98  	}
    99  
   100  	out, err = generate(tmplAddchainExp12, "0x600000000058f98a", "gfP12")
   101  	if err != nil {
   102  		log.Fatal(err)
   103  	}
   104  	if err = writeFile("gfp12_exp_u.go", out); err != nil {
   105  		log.Fatal(err)
   106  	}
   107  }
   108  
   109  const tmplAddchainExp1 = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT.
   110  package bn256
   111  
   112  func (e *Element) expPMinus1Over4(x *Element) *Element {
   113  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
   114  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
   115  	//
   116  	{{- range lines (format .Script) }}
   117  	//	{{ . }}
   118  	{{- end }}
   119  	//
   120  	var z = new(Element).Set(e)
   121  	{{- range .Program.Temporaries }}
   122  	var {{ . }} = new(Element)
   123  	{{- end }}
   124  	{{ range $i := .Program.Instructions -}}
   125  	{{- with add $i.Op }}
   126  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
   127  	{{- end -}}
   128  	{{- with double $i.Op }}
   129  	{{ $i.Output }}.Square({{ .X }})
   130  	{{- end -}}
   131  	{{- with shift $i.Op -}}
   132  	{{- $first := 0 -}}
   133  	{{- if ne $i.Output.Identifier .X.Identifier }}
   134  	{{ $i.Output }}.Square({{ .X }})
   135  	{{- $first = 1 -}}
   136  	{{- end }}
   137  	for s := {{ $first }}; s < {{ .S }}; s++ {
   138  		{{ $i.Output }}.Square({{ $i.Output }})
   139  	}
   140  	{{- end -}}
   141  	{{- end }}
   142  	return e.Set(z)
   143  }
   144  `
   145  
   146  const tmplAddchainExp2 = `
   147  func (e *Element) expP(x *Element) *Element {
   148  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
   149  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
   150  	//
   151  	{{- range lines (format .Script) }}
   152  	//	{{ . }}
   153  	{{- end }}
   154  	//
   155  	var z = new(Element).Set(e)
   156  	{{- range .Program.Temporaries }}
   157  	var {{ . }} = new(Element)
   158  	{{- end }}
   159  	{{ range $i := .Program.Instructions -}}
   160  	{{- with add $i.Op }}
   161  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
   162  	{{- end -}}
   163  	{{- with double $i.Op }}
   164  	{{ $i.Output }}.Square({{ .X }})
   165  	{{- end -}}
   166  	{{- with shift $i.Op -}}
   167  	{{- $first := 0 -}}
   168  	{{- if ne $i.Output.Identifier .X.Identifier }}
   169  	{{ $i.Output }}.Square({{ .X }})
   170  	{{- $first = 1 -}}
   171  	{{- end }}
   172  	for s := {{ $first }}; s < {{ .S }}; s++ {
   173  		{{ $i.Output }}.Square({{ $i.Output }})
   174  	}
   175  	{{- end -}}
   176  	{{- end }}
   177  	return e.Set(z)
   178  }
   179  `
   180  
   181  const tmplAddchainExp3 = `
   182  func (e *Element) expPMinus1Over2(x *Element) *Element {
   183  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
   184  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
   185  	//
   186  	{{- range lines (format .Script) }}
   187  	//	{{ . }}
   188  	{{- end }}
   189  	//
   190  	var z = new(Element).Set(e)
   191  	{{- range .Program.Temporaries }}
   192  	var {{ . }} = new(Element)
   193  	{{- end }}
   194  	{{ range $i := .Program.Instructions -}}
   195  	{{- with add $i.Op }}
   196  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
   197  	{{- end -}}
   198  	{{- with double $i.Op }}
   199  	{{ $i.Output }}.Square({{ .X }})
   200  	{{- end -}}
   201  	{{- with shift $i.Op -}}
   202  	{{- $first := 0 -}}
   203  	{{- if ne $i.Output.Identifier .X.Identifier }}
   204  	{{ $i.Output }}.Square({{ .X }})
   205  	{{- $first = 1 -}}
   206  	{{- end }}
   207  	for s := {{ $first }}; s < {{ .S }}; s++ {
   208  		{{ $i.Output }}.Square({{ $i.Output }})
   209  	}
   210  	{{- end -}}
   211  	{{- end }}
   212  	return e.Set(z)
   213  }
   214  `
   215  
   216  const tmplAddchainInvert = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT.
   217  package bn256
   218  // Invert sets e = 1/x, and returns e.
   219  //
   220  // If x == 0, Invert returns e = 0.
   221  func (e *Element) Invert(x *Element) *Element {
   222  	// Inversion is implemented as exponentiation with exponent p − 2.
   223  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
   224  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
   225  	//
   226  	{{- range lines (format .Script) }}
   227  	//	{{ . }}
   228  	{{- end }}
   229  	//
   230  	var z = new(Element).Set(e)
   231  	{{- range .Program.Temporaries }}
   232  	var {{ . }} = new(Element)
   233  	{{- end }}
   234  	{{ range $i := .Program.Instructions -}}
   235  	{{- with add $i.Op }}
   236  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
   237  	{{- end -}}
   238  	{{- with double $i.Op }}
   239  	{{ $i.Output }}.Square({{ .X }})
   240  	{{- end -}}
   241  	{{- with shift $i.Op -}}
   242  	{{- $first := 0 -}}
   243  	{{- if ne $i.Output.Identifier .X.Identifier }}
   244  	{{ $i.Output }}.Square({{ .X }})
   245  	{{- $first = 1 -}}
   246  	{{- end }}
   247  	for s := {{ $first }}; s < {{ .S }}; s++ {
   248  		{{ $i.Output }}.Square({{ $i.Output }})
   249  	}
   250  	{{- end -}}
   251  	{{- end }}
   252  	return e.Set(z)
   253  }
   254  `
   255  
   256  const tmplAddchainSqrt = `
   257  // Sqrt sets e to a square root of x. If x is not a square, Sqrt returns
   258  // false and e is unchanged. e and x can overlap.
   259  func Sqrt(e, x *Element) (isSquare bool) {
   260  	candidate, b, i := &gfP{}, &gfP{}, &gfP{}
   261  	sqrtCandidate(candidate, x)
   262  	gfpMul(b, twoExpPMinus5Over8, candidate) // b=ta1
   263  	gfpMul(candidate, x, b)                  // a1=fb
   264  	gfpMul(i, two, candidate)                // i=2(fb)
   265  	gfpMul(i, i, b)                   // i=2(fb)b
   266  	gfpSub(i, i, one)                 // i=2(fb)b-1
   267  	gfpMul(i, candidate, i)                  // i=(fb)(2(fb)b-1)
   268  	square := new(Element).Square(i)
   269  	if square.Equal(x) != 1 {
   270  		return false
   271  	}
   272  	e.Set(i)
   273  	return true
   274  }
   275  
   276  // sqrtCandidate sets z to a square root candidate for x. z and x must not overlap.
   277  func sqrtCandidate(z, x *Element) {
   278  	// Since p = 8k+5, exponentiation by (p - 5) / 8 yields a square root candidate.
   279  	//
   280  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
   281  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
   282  	//
   283  	{{- range lines (format .Script) }}
   284  	//	{{ . }}
   285  	{{- end }}
   286  	//
   287  	{{- range .Program.Temporaries }}
   288  	var {{ . }} = new(Element)
   289  	{{- end }}
   290  	{{ range $i := .Program.Instructions -}}
   291  	{{- with add $i.Op }}
   292  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
   293  	{{- end -}}
   294  	{{- with double $i.Op }}
   295  	{{ $i.Output }}.Square({{ .X }})
   296  	{{- end -}}
   297  	{{- with shift $i.Op -}}
   298  	{{- $first := 0 -}}
   299  	{{- if ne $i.Output.Identifier .X.Identifier }}
   300  	{{ $i.Output }}.Square({{ .X }})
   301  	{{- $first = 1 -}}
   302  	{{- end }}
   303  	for s := {{ $first }}; s < {{ .S }}; s++ {
   304  		{{ $i.Output }}.Square({{ $i.Output }})
   305  	}
   306  	{{- end -}}
   307  	{{- end }}
   308  }
   309  `
   310  
   311  const tmplAddchainExp12 = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT.
   312  package bn256
   313  
   314  func (e *Element) gfP12ExpU(x *Element) *Element {
   315  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
   316  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
   317  	//
   318  	{{- range lines (format .Script) }}
   319  	//	{{ . }}
   320  	{{- end }}
   321  	//
   322  	var z = new(Element).Set(e)
   323  	{{- range .Program.Temporaries }}
   324  	var {{ . }} = new(Element)
   325  	{{- end }}
   326  	{{ range $i := .Program.Instructions -}}
   327  	{{- with add $i.Op }}
   328  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
   329  	{{- end -}}
   330  	{{- with double $i.Op }}
   331  	{{ $i.Output }}.Square({{ .X }})
   332  	{{- end -}}
   333  	{{- with shift $i.Op -}}
   334  	{{- $first := 0 -}}
   335  	{{- if ne $i.Output.Identifier .X.Identifier }}
   336  	{{ $i.Output }}.Square({{ .X }})
   337  	{{- $first = 1 -}}
   338  	{{- end }}
   339  	for s := {{ $first }}; s < {{ .S }}; s++ {
   340  		{{ $i.Output }}.Square({{ $i.Output }})
   341  	}
   342  	{{- end -}}
   343  	{{- end }}
   344  	return e.Set(z)
   345  }
   346  `