Skip to content

Commit

Permalink
cmd/abigen: refactor command line interface (ethereum#19797)
Browse files Browse the repository at this point in the history
  • Loading branch information
gzliudan committed Dec 21, 2024
1 parent ea790a0 commit a1d4edf
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 91 deletions.
133 changes: 59 additions & 74 deletions cmd/abigen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strings"

"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
"github.com/XinFinOrg/XDPoSChain/common/compiler"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/internal/flags"
Expand Down Expand Up @@ -52,6 +53,10 @@ var (
Name: "type",
Usage: "Struct name for the binding (default = package name)",
}
jsonFlag = &cli.StringFlag{
Name: "combined-json",
Usage: "Path to the combined-json file generated by compiler",
}
solFlag = &cli.StringFlag{
Name: "sol",
Usage: "Path to the Ethereum contract Solidity source to build and bind",
Expand Down Expand Up @@ -96,6 +101,7 @@ func init() {
abiFlag,
binFlag,
typeFlag,
jsonFlag,
solFlag,
solcFlag,
vyFlag,
Expand All @@ -109,28 +115,11 @@ func init() {
}

func abigen(c *cli.Context) error {
if c.String(abiFlag.Name) == "" && c.String(solFlag.Name) == "" && c.String(vyFlag.Name) == "" {
fmt.Printf("No contract ABI (--abi), Solidity source (--sol), or Vyper source (--vy) specified\n")
os.Exit(-1)
} else if (c.String(abiFlag.Name) != "" || c.String(binFlag.Name) != "" || c.String(typeFlag.Name) != "") && (c.String(solFlag.Name) != "" || c.String(vyFlag.Name) != "") {
fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity (--sol) and Vyper (--vy) flags\n")
os.Exit(-1)
} else if c.String(solFlag.Name) != "" && c.String(vyFlag.Name) == "" {
fmt.Printf("Solidity (--sol) and Vyper (--vy) flags are mutually exclusive\n")
os.Exit(-1)
}
utils.CheckExclusive(c, abiFlag, jsonFlag, solFlag, vyFlag) // Only one source can be selected.
if c.String(pkgFlag.Name) == "" {
fmt.Printf("No destination package specified (--pkg)\n")
os.Exit(-1)
}
var lang bind.Lang
switch c.String(langFlag.Name) {
case "go":
lang = bind.LangGo
default:
fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", c.String(langFlag.Name))
os.Exit(-1)
utils.Fatalf("No destination package specified (--pkg)")
}
lang := bind.LangGo
// If the entire solidity code was specified, build and bind based on that
var (
abis []string
Expand All @@ -139,96 +128,100 @@ func abigen(c *cli.Context) error {
sigs []map[string]string
libs = make(map[string]string)
)
if c.String(solFlag.Name) != "" || c.String(vyFlag.Name) != "" || c.String(abiFlag.Name) == "-" {
if c.String(abiFlag.Name) != "" {
// Load up the ABI, optional bytecode and type name from the parameters
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)
}
abis = append(abis, string(abi))

var bin []byte
if binFile := c.String(binFlag.Name); binFile != "" {
if bin, err = os.ReadFile(binFile); err != nil {
utils.Fatalf("Failed to read input bytecode: %v", err)
}
if strings.Contains(string(bin), "//") {
utils.Fatalf("Contract has additional library references, please use other mode(e.g. --combined-json) to catch library infos")
}
}
bins = append(bins, string(bin))

kind := c.String(typeFlag.Name)
if kind == "" {
kind = c.String(pkgFlag.Name)
}
types = append(types, kind)
} else {
// Generate the list of types to exclude from binding
exclude := make(map[string]bool)
for _, kind := range strings.Split(c.String(excFlag.Name), ",") {
exclude[strings.ToLower(kind)] = true
}

var contracts map[string]*compiler.Contract
var err error
var contracts map[string]*compiler.Contract

switch {
case c.String(solFlag.Name) != "":
case c.IsSet(solFlag.Name):
contracts, err = compiler.CompileSolidity(c.String(solcFlag.Name), c.String(solFlag.Name))
if err != nil {
fmt.Printf("Failed to build Solidity contract: %v\n", err)
os.Exit(-1)
utils.Fatalf("Failed to build Solidity contract: %v", err)
}
case c.String(vyFlag.Name) != "":
case c.IsSet(vyFlag.Name):
contracts, err = compiler.CompileVyper(c.String(vyperFlag.Name), c.String(vyFlag.Name))
if err != nil {
fmt.Printf("Failed to build Vyper contract: %v\n", err)
os.Exit(-1)
utils.Fatalf("Failed to build Vyper contract: %v", err)
}
default:
contracts, err = contractsFromStdin()
case c.IsSet(jsonFlag.Name):
jsonOutput, err := os.ReadFile(c.String(jsonFlag.Name))
if err != nil {
fmt.Printf("Failed to read input ABIs from STDIN: %v\n", err)
os.Exit(-1)
utils.Fatalf("Failed to read combined-json from compiler: %v", err)
}
contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "")
if err != nil {
utils.Fatalf("Failed to read contract information from json output: %v", err)
}
}

// Gather all non-excluded contract for binding
for name, contract := range contracts {
if exclude[strings.ToLower(name)] {
continue
}
abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
if err != nil {
fmt.Printf("Failed to parse ABIs from compiler output: %v\n", err)
os.Exit(-1)
utils.Fatalf("Failed to parse ABIs from compiler output: %v", err)
}
abis = append(abis, string(abi))
bins = append(bins, contract.Code)
sigs = append(sigs, contract.Hashes)

nameParts := strings.Split(name, ":")
types = append(types, nameParts[len(nameParts)-1])

libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36]
libs[libPattern] = nameParts[len(nameParts)-1]
}
} else {
// Otherwise load up the ABI, optional bytecode and type name from the parameters
abi, err := os.ReadFile(c.String(abiFlag.Name))

if err != nil {
fmt.Printf("Failed to read input ABI: %v\n", err)
os.Exit(-1)
}
abis = append(abis, string(abi))

var bin []byte
if c.String(binFlag.Name) != "" {
if bin, err = os.ReadFile(c.String(binFlag.Name)); err != nil {
fmt.Printf("Failed to read input bytecode: %v\n", err)
os.Exit(-1)
}
}
bins = append(bins, string(bin))

kind := c.String(typeFlag.Name)
if kind == "" {
kind = c.String(pkgFlag.Name)
}
types = append(types, kind)
}
// Generate the contract binding
code, err := bind.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), lang, libs)
if err != nil {
fmt.Printf("Failed to generate ABI binding: %v\n", err)
os.Exit(-1)
utils.Fatalf("Failed to generate ABI binding: %v", err)
}
// Either flush it out to a file or display on the standard output
if c.String(outFlag.Name) == "" {
if !c.IsSet(outFlag.Name) {
fmt.Printf("%s\n", code)
return nil
}
if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil {
fmt.Printf("Failed to write ABI binding: %v\n", err)
os.Exit(-1)
utils.Fatalf("Failed to write ABI binding: %v", err)
}
return nil
}
Expand All @@ -241,11 +234,3 @@ func main() {
os.Exit(1)
}
}

func contractsFromStdin() (map[string]*compiler.Contract, error) {
bytes, err := io.ReadAll(os.Stdin)
if err != nil {
return nil, err
}
return compiler.ParseCombinedJSON(bytes, "", "", "", "")
}
16 changes: 8 additions & 8 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ func setWS(ctx *cli.Context, cfg *node.Config) {
// setIPC creates an IPC path configuration from the set command line flags,
// returning an empty string if IPC was explicitly disabled, or the set path.
func setIPC(ctx *cli.Context, cfg *node.Config) {
checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
switch {
case ctx.Bool(IPCDisabledFlag.Name):
cfg.IPCPath = ""
Expand All @@ -1034,7 +1034,7 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
}

func setPrefix(ctx *cli.Context, cfg *node.Config) {
checkExclusive(ctx, Enable0xPrefixFlag, EnableXDCPrefixFlag)
CheckExclusive(ctx, Enable0xPrefixFlag, EnableXDCPrefixFlag)
}

// MakeDatabaseHandles raises out the number of allowed file handles per process
Expand Down Expand Up @@ -1301,10 +1301,10 @@ func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
}
}

// checkExclusive verifies that only a single isntance of the provided flags was
// CheckExclusive verifies that only a single isntance of the provided flags was
// set by the user. Each flag might optionally be followed by a string type to
// specialize it further.
func checkExclusive(ctx *cli.Context, args ...interface{}) {
func CheckExclusive(ctx *cli.Context, args ...interface{}) {
set := make([]string, 0, 1)
for i := 0; i < len(args); i++ {
// Make sure the next argument is a flag and skip if not set
Expand Down Expand Up @@ -1381,10 +1381,10 @@ func SetXDCXConfig(ctx *cli.Context, cfg *XDCx.Config, XDCDataDir string) {
// SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Avoid conflicting network flags
checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
checkExclusive(ctx, LightServFlag, LightModeFlag)
checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
CheckExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
CheckExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
CheckExclusive(ctx, LightServFlag, LightModeFlag)
CheckExclusive(ctx, LightServFlag, SyncModeFlag, "light")

ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
setEtherbase(ctx, ks, cfg)
Expand Down
13 changes: 4 additions & 9 deletions common/compiler/solidity.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin
if err := json.Unmarshal(combinedJSON, &output); err != nil {
return nil, err
}

// Compilation succeeded, assemble and return the contracts.
contracts := make(map[string]*Contract)
for name, info := range output.Contracts {
Expand All @@ -151,14 +150,10 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin
if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil {
return nil, fmt.Errorf("solc: error reading abi definition (%v)", err)
}
var userdoc interface{}
if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil {
return nil, fmt.Errorf("solc: error reading user doc: %v", err)
}
var devdoc interface{}
if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil {
return nil, fmt.Errorf("solc: error reading dev doc: %v", err)
}
var userdoc, devdoc interface{}
json.Unmarshal([]byte(info.Userdoc), &userdoc)
json.Unmarshal([]byte(info.Devdoc), &devdoc)

contracts[name] = &Contract{
Code: "0x" + info.Bin,
RuntimeCode: "0x" + info.BinRuntime,
Expand Down

0 comments on commit a1d4edf

Please sign in to comment.