Skip to content

Commit

Permalink
feat: update bindings for V2
Browse files Browse the repository at this point in the history
  • Loading branch information
henriquemarlon committed Nov 16, 2024
1 parent b3c773a commit 00f7963
Show file tree
Hide file tree
Showing 10 changed files with 1,672 additions and 1,238 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ coverage: test
.PHONY: docs
docs:
@cd docs && npm run dev

.PHONY: generate
generate:
@go run ./pkg/rollups_contracts/generate
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package crowdfunding_usecase
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package crowdfunding_usecase
990 changes: 990 additions & 0 deletions pkg/rollups_contracts/application.go

Large diffs are not rendered by default.

995 changes: 0 additions & 995 deletions pkg/rollups_contracts/cartesi_dapp.go

This file was deleted.

384 changes: 384 additions & 0 deletions pkg/rollups_contracts/eip712.go

Large diffs are not rendered by default.

132 changes: 66 additions & 66 deletions pkg/rollups_contracts/erc20_portal.go

Large diffs are not rendered by default.

158 changes: 104 additions & 54 deletions pkg/rollups_contracts/generate/main.go
Original file line number Diff line number Diff line change
@@ -1,144 +1,194 @@
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

// This binary generates the Go bindings for the Cartesi Rollups crowdfundings.
// This binary should be called with `go generate` in the parent dir.
// First, it downloads the Cartesi Rollups npm package containing the crowdfundings.
// Then, it generates the bindings using abi-gen.
// Finally, it stores the bindings in the current directory.
package main

import (
"archive/tar"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"log"
"log/slog"
"net/http"
"os"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
)

const rollupsCrowdfundingsUrl = "https://registry.npmjs.org/@cartesi/rollups/-/rollups-1.4.0.tgz"
const baseCrowdfundingsPath = "package/export/artifacts/crowdfundings/"
const bindingPkg = "rollups_crowdfundings"
const (
openzeppelin = "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz"
rollupsContractsUrl = "https://registry.npmjs.org/@cartesi/rollups/-/rollups-2.0.0-rc.10.tgz"
baseContractsPath = "package/export/artifacts/contracts/"
bindingPkg = "rollups_contracts"
)

type crowdfundingBinding struct {
type contractBinding struct {
jsonPath string
typeName string
outFile string
}

var bindings = []crowdfundingBinding{
var bindings = []contractBinding{
{
jsonPath: "package/build/contracts/EIP712.json",
typeName: "EIP712",
outFile: "./pkg/rollups_contracts/eip712.go",
},
{
jsonPath: baseCrowdfundingsPath + "inputs/InputBox.sol/InputBox.json",
jsonPath: baseContractsPath + "inputs/InputBox.sol/InputBox.json",
typeName: "InputBox",
outFile: "./pkg/rollups_crowdfundings/input_box.go",
outFile: "./pkg/rollups_contracts/input_box.go",
},
{
jsonPath: baseCrowdfundingsPath + "portals/ERC20Portal.sol/ERC20Portal.json",
typeName: "ERC20Portal",
outFile: "./pkg/rollups_crowdfundings/erc20_portal.go",
jsonPath: baseContractsPath + "dapp/Application.sol/Application.json",
typeName: "Application",
outFile: "./pkg/rollups_contracts/application.go",
},
{
jsonPath: baseCrowdfundingsPath + "dapp/CartesiDApp.sol/CartesiDApp.json",
typeName: "CartesiDApp",
outFile: "./pkg/rollups_crowdfundings/cartesi_dapp.go",
jsonPath: baseContractsPath + "portals/ERC20Portal.sol/ERC20Portal.json",
typeName: "ERC20Portal",
outFile: "./pkg/rollups_contracts/erc20_portal.go",
},
}

func main() {
crowdfundingsZip := downloadCrowdfundings(rollupsCrowdfundingsUrl)
defer crowdfundingsZip.Close()
crowdfundingsTar := unzip(crowdfundingsZip)
defer crowdfundingsTar.Close()
// Configurar logs detalhados
slog.Info("Starting contract bindings generation")

// Baixar e descompactar pacotes de contratos
contractsZip, err := downloadContracts(rollupsContractsUrl)
checkErr("download contracts", err)
defer contractsZip.Close()

contractsTar, err := unzip(contractsZip)
checkErr("unzip contracts", err)
defer contractsTar.Close()

contractsOpenZeppelin, err := downloadContracts(openzeppelin)
checkErr("download OpenZeppelin contracts", err)
defer contractsOpenZeppelin.Close()

contractsTarOpenZeppelin, err := unzip(contractsOpenZeppelin)
checkErr("unzip OpenZeppelin contracts", err)
defer contractsTarOpenZeppelin.Close()

// Mapear arquivos necessários
files := make(map[string]bool)
for _, b := range bindings {
files[b.jsonPath] = true
}
contents := readFilesFromTar(crowdfundingsTar, files)

contents, err := readFilesFromTar(contractsTar, files)
checkErr("read files from tar (Rollups)", err)

contentsZ, err := readFilesFromTar(contractsTarOpenZeppelin, files)
checkErr("read files from tar (OpenZeppelin)", err)

// Mesclar conteúdos de ambos os pacotes
for key, content := range contentsZ {
contents[key] = content
}

// Gerar bindings para cada contrato
for _, b := range bindings {
content := contents[b.jsonPath]
if content == nil {
log.Fatal("missing contents for ", b.jsonPath)
log.Fatalf("missing contents for %s", b.jsonPath)
}
generateBinding(b, content)
}

slog.Info("Contract bindings generation completed successfully")
}

// Exit if there is any error.
func checkErr(context string, err any) {
if err != nil {
log.Fatal(context, ": ", err)
log.Fatalf("%s: %v", context, err)
}
}

// Download the crowdfundings from rollupsCrowdfundingsUrl.
// Return the buffer with the crowdfundings.
func downloadCrowdfundings(url string) io.ReadCloser {
log.Print("downloading crowdfundings from ", url)
// Download the contracts from the provided URL.
func downloadContracts(url string) (io.ReadCloser, error) {
slog.Info("Downloading contracts", slog.String("url", url))
response, err := http.Get(url)
checkErr("download tgz", err)
if err != nil {
return nil, fmt.Errorf("failed to download contracts from %s: %w", url, err)
}
if response.StatusCode != http.StatusOK {
response.Body.Close()
log.Fatal("invalid status: ", response.Status)
defer response.Body.Close()
return nil, fmt.Errorf("failed to download contracts from %s: status code %s", url, response.Status)
}
return response.Body
return response.Body, nil
}

// Decompress the buffer with the crowdfundings.
func unzip(r io.Reader) io.ReadCloser {
log.Print("unziping crowdfundings")
// Decompress the buffer with the contracts.
func unzip(r io.Reader) (io.ReadCloser, error) {
slog.Info("Unzipping contracts")
gzipReader, err := gzip.NewReader(r)
checkErr("unziping", err)
return gzipReader
if err != nil {
return nil, fmt.Errorf("failed to unzip: %w", err)
}
return gzipReader, nil
}

// Read the required files from the tar.
// Return a map with the file contents.
func readFilesFromTar(r io.Reader, files map[string]bool) map[string][]byte {
// Read the required files from the tar archive.
func readFilesFromTar(r io.Reader, files map[string]bool) (map[string][]byte, error) {
contents := make(map[string][]byte)
tarReader := tar.NewReader(r)

for {
header, err := tarReader.Next()
if err == io.EOF {
break // End of archive
}
checkErr("read tar", err)
if err != nil {
return nil, fmt.Errorf("error while reading tar: %w", err)
}

if files[header.Name] {
slog.Info("Found file in tar", slog.String("name", header.Name))
contents[header.Name], err = io.ReadAll(tarReader)
checkErr("read tar", err)
if err != nil {
return nil, fmt.Errorf("error while reading file inside tar: %w", err)
}
}
}
return contents
return contents, nil
}

// Get the .abi key from the json
// Extract the ABI from the contract JSON.
func getAbi(rawJson []byte) []byte {
var contents struct {
Abi json.RawMessage `json:"abi"`
}
err := json.Unmarshal(rawJson, &contents)
checkErr("decode json", err)
checkErr("decode JSON", err)
return contents.Abi
}

// Generate the Go bindings for the crowdfundings.
func generateBinding(b crowdfundingBinding, content []byte) {
// Generate the Go bindings for the contracts.
func generateBinding(b contractBinding, content []byte) {
// Ensure the output directory exists
err := os.MkdirAll("./pkg/rollups_contracts", 0755)
checkErr("create output directory", err)

// Prepare binding parameters
abi := getAbi(content)
var (
sigs []map[string]string
abis = []string{string(getAbi(content))}
abis = []string{string(abi)}
bins = []string{""}
types = []string{b.typeName}
libs = make(map[string]string)
aliases = make(map[string]string)
)

// Generate bindings
code, err := bind.Bind(types, abis, bins, sigs, bindingPkg, bind.LangGo, libs, aliases)
checkErr("generate binding", err)
const fileMode = 0600
err = os.WriteFile(b.outFile, []byte(code), fileMode)

// Write binding to file
err = os.WriteFile(b.outFile, []byte(code), 0600)
checkErr("write binding file", err)
log.Print("generated binding ", b.outFile)
slog.Info("Generated binding", slog.String("file", b.outFile))
}
Loading

0 comments on commit 00f7963

Please sign in to comment.