mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
199 lines
5.3 KiB
Go
199 lines
5.3 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
//
|
|
// 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/cmd/utils"
|
|
"github.com/luxfi/evm/internal/flags"
|
|
"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() {
|
|
// Setup logging - use default logger
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|