Skip to content
Merged
6 changes: 6 additions & 0 deletions crates/batcher/go_verifiers_lib/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ module verifier

go 1.22.3

replace github.com/iden3/go-rapidsnark => github.com/MarcosNicolau/go-rapidsnark v0.0.0-20250828172020-87df0a23ada4
Comment thread
MarcosNicolau marked this conversation as resolved.
Outdated

replace github.com/iden3/go-rapidsnark/types => github.com/MarcosNicolau/go-rapidsnark/types v0.0.0-20250828172020-87df0a23ada4

replace github.com/iden3/go-rapidsnark/verifier => github.com/MarcosNicolau/go-rapidsnark/verifier v0.0.0-20250828172020-87df0a23ada4

require (
github.com/consensys/gnark v0.12.0
github.com/consensys/gnark-crypto v0.17.0
Expand Down
8 changes: 4 additions & 4 deletions crates/batcher/go_verifiers_lib/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
github.com/MarcosNicolau/go-rapidsnark/types v0.0.0-20250828172020-87df0a23ada4 h1:NAZOH8mk5hgWpxf1ujVw+uggsRBMcXiiC7R7sZXVfW0=
github.com/MarcosNicolau/go-rapidsnark/types v0.0.0-20250828172020-87df0a23ada4/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4=
github.com/MarcosNicolau/go-rapidsnark/verifier v0.0.0-20250828172020-87df0a23ada4 h1:Sz8H0fl9kjg8iZmaHT8pyCx4Smy5JJtq0OyKfz8iXls=
github.com/MarcosNicolau/go-rapidsnark/verifier v0.0.0-20250828172020-87df0a23ada4/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI=
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
Expand All @@ -21,10 +25,6 @@ github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/iden3/go-iden3-crypto v0.0.17 h1:NdkceRLJo/pI4UpcjVah4lN/a3yzxRUGXqxbWcYh9mY=
github.com/iden3/go-iden3-crypto v0.0.17/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E=
github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4=
github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4=
github.com/iden3/go-rapidsnark/verifier v0.0.5 h1:J7y0ovrEjDQoWtZmlrp4tgGng1A9faMeYsQH4igAEqA=
github.com/iden3/go-rapidsnark/verifier v0.0.5/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI=
github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b h1:AvQTK7l0PTHODD06PVQX1Tn2o29sRIaKIDOvTJmKurY=
github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b/go.mod h1:e0JHb27/P6WorCJS3YolbY5XffS4PGBuoW38OthLkDs=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
Expand Down
45 changes: 35 additions & 10 deletions crates/batcher/go_verifiers_lib/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import "C"
import (
"bytes"
"encoding/json"
"github.com/iden3/go-rapidsnark/types"
"github.com/iden3/go-rapidsnark/verifier"
"math/big"

"log"
"unsafe"
Expand All @@ -24,6 +23,8 @@ import (
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/backend/plonk"
"github.com/consensys/gnark/backend/witness"
"github.com/iden3/go-rapidsnark/types"
"github.com/iden3/go-rapidsnark/verifier"
)

func listRefToBytes(listRef C.ListRef) []byte {
Expand Down Expand Up @@ -122,6 +123,20 @@ func verifyGnarkGroth16Proof(proofBytesRef C.ListRef, pubInputBytesRef C.ListRef
return err == nil
}

func bytesToBigInts32(b []byte) []*big.Int {
if len(b)%32 != 0 {
panic("pubInputBytes length is not a multiple of 32")
}

inputs := make([]*big.Int, 0, len(b)/32)
for i := 0; i < len(b); i += 32 {
chunk := b[i : i+32]
bi := new(big.Int).SetBytes(chunk)
inputs = append(inputs, bi)
}
return inputs
}

//export VerifyCircomGroth16ProofBN256
func VerifyCircomGroth16ProofBN256(proofBytesRef C.ListRef, pubInputBytesRef C.ListRef, verificationKeyBytesRef C.ListRef) bool {
proofBytes := listRefToBytes(proofBytesRef)
Expand All @@ -131,26 +146,36 @@ func VerifyCircomGroth16ProofBN256(proofBytesRef C.ListRef, pubInputBytesRef C.L
proofData := &types.ProofData{}
err := json.Unmarshal(proofBytes, proofData)
if err != nil {
log.Printf("Could not marshal proof: %v", err)
log.Printf("Could not unmarshal proof: %v", err)
return false
}

var pubSignals []string
err = json.Unmarshal(pubInputBytes, &pubSignals)
parsedProofData, err := verifier.ParseProofData(*proofData)
if err != nil {
log.Printf("Error unmarshaling JSON: %v", err)
log.Printf("Could not parse proof: %v", err)
return false
}

zkProof := types.ZKProof{
Proof: proofData,
PubSignals: pubSignals,
var vkStr verifier.VkJSON
err = json.Unmarshal(verificationKeyBytes, &vkStr)
if err != nil {
log.Printf("Could not unmarshal vk: %v", err)
return false
}

vk, err := verifier.ParseVK(vkStr)
if err != nil {
log.Printf("Could not parse vk: %v", err)
return false
}

err = verifier.VerifyGroth16(zkProof, verificationKeyBytes)
inputs := bytesToBigInts32(pubInputBytes)

err = verifier.VerifyRaw(vk, parsedProofData, inputs)
if err != nil {
log.Printf("Could not verify Groth16 proof: %v", err)
return false
}

return true
}
15 changes: 11 additions & 4 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,10 +926,17 @@ fn verification_data_from_args(args: &SubmitArgs) -> Result<VerificationData, Su
"--vk",
args.verification_key_file_name.clone(),
)?);
pub_input = Some(read_file_option(
"--public_input",
args.pub_input_file_name.clone(),
)?);
let pub_input_file =
read_file_option("--public_input", args.pub_input_file_name.clone())?;
let pub_inputs: Vec<String> = serde_json::from_slice(&pub_input_file)
.map_err(|e| SubmitError::MissingRequiredParameter(e.to_string()))?;

let decode_inputs = aligned_sdk::common::utils::encode_circom_pub_inputs(&pub_inputs)
.map_err(|_| {
SubmitError::MissingRequiredParameter("Invalid public inputs".into())
})?;

pub_input = Some(decode_inputs);
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/sdk/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod constants;
pub mod errors;
pub mod types;
pub mod utils;
32 changes: 32 additions & 0 deletions crates/sdk/src/common/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use ethers::{abi::ethereum_types::FromDecStrErr, types::U256};

/// Encodes Circom public inputs into a single byte vector.
///
/// Circom normally outputs public inputs as a JSON array of strings, where each
/// entry is actually a big integer represented in decimal. For example:
///
/// ```json
/// { "pubInputs": ["123", "456", "789"] }
/// ```
///
/// For on-chain usage (e.g. in Solidity), working with JSON is inefficient.
/// Instead, we prefer the **raw form**: each input is converted to a 32-byte
/// big-endian encoding of the integer, concatenated together. This makes it
/// simple to compute commitments and verify proofs on-chain, since the contract
/// receives a compact `bytes` array rather than parsing JSON.
///
/// Each input must fit in 32 bytes (i.e. < 2^256).
pub fn encode_circom_pub_inputs(input: &[String]) -> Result<Vec<u8>, FromDecStrErr> {
let mut out = Vec::with_capacity(input.len() * 32);

for s in input {
// parse as decimal (base 10). Use from_str_radix(s, 16) if they're hex.
let n = U256::from_dec_str(s)?;
let mut bytes = [0u8; 32];
n.to_big_endian(&mut bytes);

out.extend_from_slice(&bytes);
}

Ok(out)
}
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ go 1.22.3

toolchain go1.23.4

replace github.com/iden3/go-rapidsnark => github.com/MarcosNicolau/go-rapidsnark v0.0.0-20250828172020-87df0a23ada4

replace github.com/iden3/go-rapidsnark/types => github.com/MarcosNicolau/go-rapidsnark/types v0.0.0-20250828172020-87df0a23ada4

replace github.com/iden3/go-rapidsnark/verifier => github.com/MarcosNicolau/go-rapidsnark/verifier v0.0.0-20250828172020-87df0a23ada4

require (
github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1
github.com/ethereum/go-ethereum v1.14.0
Expand All @@ -18,7 +24,6 @@ require (
github.com/consensys/gnark v0.12.0
github.com/consensys/gnark-crypto v0.17.0
github.com/fxamacker/cbor/v2 v2.7.0
github.com/iden3/go-rapidsnark/types v0.0.3
github.com/iden3/go-rapidsnark/verifier v0.0.5
github.com/rs/zerolog v1.33.0
github.com/ugorji/go/codec v1.2.12
Expand Down Expand Up @@ -63,6 +68,7 @@ require (
github.com/gorilla/websocket v1.5.1 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/iden3/go-iden3-crypto v0.0.17 // indirect
github.com/iden3/go-rapidsnark/types v0.0.3 // indirect
github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/lmittmann/tint v1.0.4 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1 h1:vW7AKcvt7fGlIeOMl2Ft9Au/ib8Z9ush8fSrpFSVr10=
github.com/Layr-Labs/eigensdk-go v0.2.0-beta.1/go.mod h1:G4yqiK+5NfUuEMVGGncOEm7QskuGRPmKA7bKxpPzPT4=
github.com/MarcosNicolau/go-rapidsnark/types v0.0.0-20250828172020-87df0a23ada4 h1:NAZOH8mk5hgWpxf1ujVw+uggsRBMcXiiC7R7sZXVfW0=
github.com/MarcosNicolau/go-rapidsnark/types v0.0.0-20250828172020-87df0a23ada4/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4=
github.com/MarcosNicolau/go-rapidsnark/verifier v0.0.0-20250828172020-87df0a23ada4 h1:Sz8H0fl9kjg8iZmaHT8pyCx4Smy5JJtq0OyKfz8iXls=
github.com/MarcosNicolau/go-rapidsnark/verifier v0.0.0-20250828172020-87df0a23ada4/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
Expand Down Expand Up @@ -192,10 +196,6 @@ github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/iden3/go-iden3-crypto v0.0.17 h1:NdkceRLJo/pI4UpcjVah4lN/a3yzxRUGXqxbWcYh9mY=
github.com/iden3/go-iden3-crypto v0.0.17/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E=
github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4=
github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4=
github.com/iden3/go-rapidsnark/verifier v0.0.5 h1:J7y0ovrEjDQoWtZmlrp4tgGng1A9faMeYsQH4igAEqA=
github.com/iden3/go-rapidsnark/verifier v0.0.5/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI=
github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b h1:AvQTK7l0PTHODD06PVQX1Tn2o29sRIaKIDOvTJmKurY=
github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b/go.mod h1:e0JHb27/P6WorCJS3YolbY5XffS4PGBuoW38OthLkDs=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
Expand Down
44 changes: 34 additions & 10 deletions operator/pkg/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"time"

rapidsnark_types "github.com/iden3/go-rapidsnark/types"
"github.com/iden3/go-rapidsnark/verifier"
rapidsnark_verifier "github.com/iden3/go-rapidsnark/verifier"

"github.com/ethereum/go-ethereum/crypto"
"github.com/urfave/cli/v2"
Expand Down Expand Up @@ -621,30 +621,54 @@ func (o *Operator) verifyGnarkGroth16Proof(proofBytes []byte, pubInputBytes []by

// verifyCircomGroth16Bn256Proof verifies a Circom Groth16 proof using BN256 curve.
func (o *Operator) verifyCircomGroth16Bn256Proof(proofBytes []byte, pubInputBytes []byte, verificationKeyBytes []byte) bool {
bytesToBigInts32 := func(b []byte) []*big.Int {
if len(b)%32 != 0 {
panic("pubInputBytes length is not a multiple of 32")
}

inputs := make([]*big.Int, 0, len(b)/32)
for i := 0; i < len(b); i += 32 {
chunk := b[i : i+32]
bi := new(big.Int).SetBytes(chunk)
inputs = append(inputs, bi)
}
return inputs
}

proofData := &rapidsnark_types.ProofData{}
err := json.Unmarshal(proofBytes, proofData)
if err != nil {
o.Logger.Infof("Could not marshal proof: %v", err)
log.Printf("Could not unmarshal proof: %v", err)
return false
}

var pubSignals []string
err = json.Unmarshal(pubInputBytes, &pubSignals)
parsedProofData, err := rapidsnark_verifier.ParseProofData(*proofData)
if err != nil {
o.Logger.Infof("Could not marshal public signals: %v", err)
log.Printf("Could not parse proof: %v", err)
return false
}

zkProof := rapidsnark_types.ZKProof{
Proof: proofData,
PubSignals: pubSignals,
var vkStr rapidsnark_verifier.VkJSON
err = json.Unmarshal(verificationKeyBytes, &vkStr)
if err != nil {
log.Printf("Could not unmarshal vk: %v", err)
return false
}

err = verifier.VerifyGroth16(zkProof, verificationKeyBytes)
vk, err := rapidsnark_verifier.ParseVK(vkStr)
if err != nil {
o.Logger.Infof("Could not verify Circom Groth16 BN256 proof: %v", err)
log.Printf("Could not parse vk: %v", err)
return false
}

inputs := bytesToBigInts32(pubInputBytes)

err = rapidsnark_verifier.VerifyRaw(vk, parsedProofData, inputs)
if err != nil {
log.Printf("Could not verify Groth16 proof: %v", err)
return false
}

return true
}

Expand Down
Loading