Files

197 lines
5.2 KiB
Go

// (c) 2020-2020, Lux Industries, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// Copyright 2016 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
_ "embed"
"github.com/luxfi/evm/accounts/abi/bind"
"github.com/luxfi/evm/accounts/abi/bind/precompilebind"
"github.com/luxfi/evm/internal/flags"
"github.com/luxfi/evm/cmd/utils"
"github.com/luxfi/log"
"github.com/urfave/cli/v2"
)
//go:embed template-readme.md
var readme string
var (
// Flags needed by abigen
abiFlag = &cli.StringFlag{
Name: "abi",
Usage: "Path to the contract ABI json to generate, - for STDIN",
}
typeFlag = &cli.StringFlag{
Name: "type",
Usage: "Struct name for the precompile (default = {abi file name})",
}
pkgFlag = &cli.StringFlag{
Name: "pkg",
Usage: "Go package name to generate the precompile into (default = {type})",
}
outFlag = &cli.StringFlag{
Name: "out",
Usage: "Output folder for the generated precompile files, - for STDOUT (default = ./precompile/contracts/{pkg}). Test files won't be generated if STDOUT is used",
}
)
var app = flags.NewApp("evm precompile generator tool")
func init() {
app.Name = "precompilegen"
app.Flags = []cli.Flag{
abiFlag,
outFlag,
pkgFlag,
typeFlag,
}
app.Action = precompilegen
}
func precompilegen(c *cli.Context) error {
outFlagStr := c.String(outFlag.Name)
isOutStdout := outFlagStr == "-"
if isOutStdout && !c.IsSet(typeFlag.Name) {
utils.Fatalf("type (--type) should be set explicitly for STDOUT ")
}
lang := bind.LangGo
// If the entire solidity code was specified, build and bind based on that
var (
bins []string
types []string
sigs []map[string]string
libs = make(map[string]string)
aliases = make(map[string]string)
)
if c.String(abiFlag.Name) == "" {
utils.Fatalf("no abi path is specified (--abi)")
}
// Load up the ABI
var (
abi []byte
err error
)
input := c.String(abiFlag.Name)
if input == "-" {
abi, err = io.ReadAll(os.Stdin)
} else {
abi, err = os.ReadFile(input)
}
if err != nil {
utils.Fatalf("Failed to read input ABI: %v", err)
}
bins = append(bins, "")
kind := c.String(typeFlag.Name)
if kind == "" {
fn := filepath.Base(input)
kind = strings.TrimSuffix(fn, filepath.Ext(fn))
kind = strings.TrimSpace(kind)
}
types = append(types, kind)
pkg := c.String(pkgFlag.Name)
if pkg == "" {
pkg = strings.ToLower(kind)
}
if outFlagStr == "" {
outFlagStr = filepath.Join("./precompile/contracts", pkg)
}
abifilename := ""
abipath := ""
// we should not generate the abi file if output is set to stdout
if !isOutStdout {
// get file name from the output path
abifilename = "contract.abi"
abipath = filepath.Join(outFlagStr, abifilename)
}
// if output is set to stdout, we should not generate the test codes
generateTests := !isOutStdout
// Generate the contract precompile
bindedFiles, err := precompilebind.PrecompileBind(types, string(abi), bins, sigs, pkg, lang, libs, aliases, abifilename, generateTests)
if err != nil {
utils.Fatalf("Failed to generate precompile: %v", err)
}
// Either flush it out to a file or display on the standard output
// Skip displaying test codes here.
if isOutStdout {
for _, file := range bindedFiles {
if !file.IsTest {
fmt.Printf("-----file: %s-----\n", file.FileName)
fmt.Printf("%s\n", file.Content)
}
}
return nil
}
if _, err := os.Stat(outFlagStr); os.IsNotExist(err) {
os.MkdirAll(outFlagStr, 0o700) // Create your file
}
for _, file := range bindedFiles {
outputPath := filepath.Join(outFlagStr, file.FileName)
if err := os.WriteFile(outputPath, []byte(file.Content), 0o600); err != nil {
utils.Fatalf("Failed to write generated file %s: %v", file.FileName, err)
}
}
// Write the ABI to the output folder
if err := os.WriteFile(abipath, abi, 0o600); err != nil {
utils.Fatalf("Failed to write ABI: %v", err)
}
// Write the README to the output folder
readmeOut := filepath.Join(outFlagStr, "README.md")
if err := os.WriteFile(readmeOut, []byte(readme), 0o600); err != nil {
utils.Fatalf("Failed to write README: %v", err)
}
fmt.Println("Precompile files generated successfully at: ", outFlagStr)
return nil
}
func main() {
log.SetDefault(log.NewLogger("precompilegen"))
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}