//go:build ignore // +build ignore package main import ( "bytes" "go/format" "io" "log" "os" "os/exec" ) // Running this generator requires addchain v0.4.0, which can be installed with // // go install github.com/mmcloughlin/addchain/cmd/addchain@v0.4.0 // func main() { tmplAddchainFile, err := os.CreateTemp("", "addchain-template") if err != nil { log.Fatal(err) } defer os.Remove(tmplAddchainFile.Name()) if _, err := io.WriteString(tmplAddchainFile, tmplAddchain); err != nil { log.Fatal(err) } if err := tmplAddchainFile.Close(); err != nil { log.Fatal(err) } log.Printf("Generating gfp_invert.go...") f, err := os.CreateTemp("", "addchain-gfp") if err != nil { log.Fatal(err) } defer os.Remove(f.Name()) cmd := exec.Command("addchain", "search", "0xb640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457b") cmd.Stderr = os.Stderr cmd.Stdout = f if err := cmd.Run(); err != nil { log.Fatal(err) } if err := f.Close(); err != nil { log.Fatal(err) } cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), f.Name()) cmd.Stderr = os.Stderr out, err := cmd.Output() if err != nil { log.Fatal(err) } out = bytes.Replace(out, []byte("Element"), []byte("gfP"), -1) out, err = format.Source(out) if err != nil { log.Fatal(err) } if err := os.WriteFile("gfp_invert.go", out, 0644); err != nil { log.Fatal(err) } } const tmplAddchain = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT. package bn256 // Invert sets e = 1/x, and returns e. // // If x == 0, Invert returns e = 0. func (e *Element) Invert(x *Element) *Element { // Inversion is implemented as exponentiation with exponent p − 2. // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. // {{- range lines (format .Script) }} // {{ . }} {{- end }} // var z = new(Element).Set(e) {{- range .Program.Temporaries }} var {{ . }} = new(Element) {{- end }} {{ range $i := .Program.Instructions -}} {{- with add $i.Op }} {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) {{- end -}} {{- with double $i.Op }} {{ $i.Output }}.Square({{ .X }}) {{- end -}} {{- with shift $i.Op -}} {{- $first := 0 -}} {{- if ne $i.Output.Identifier .X.Identifier }} {{ $i.Output }}.Square({{ .X }}) {{- $first = 1 -}} {{- end }} for s := {{ $first }}; s < {{ .S }}; s++ { {{ $i.Output }}.Square({{ $i.Output }}) } {{- end -}} {{- end }} return e.Set(z) } `