Skip to content

Commit 55a29b6

Browse files
authored
Embedded VK in the recursive circuit (#5296)
2 parents 3e04d9b + 0ab0190 commit 55a29b6

File tree

5 files changed

+147
-45
lines changed

5 files changed

+147
-45
lines changed

galoisd/grpc/bls12381_server.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
grpc "galois/grpc/api/v3"
1212
"galois/pkg/lightclient"
1313
bls12381gadget "galois/pkg/lightclient/bls12381"
14+
1415
// "io"
1516
"math/big"
1617
"os"
@@ -29,7 +30,6 @@ import (
2930
cs_bls12381 "github.com/consensys/gnark/constraint/bls12-381"
3031
cs_bn254 "github.com/consensys/gnark/constraint/bn254"
3132
"github.com/consensys/gnark/frontend"
32-
"github.com/consensys/gnark/frontend/cs/r1cs"
3333
gadget "github.com/consensys/gnark/std/algebra/emulated/sw_bn254"
3434
"github.com/consensys/gnark/std/recursion/groth16"
3535
"github.com/holiman/uint256"
@@ -118,10 +118,8 @@ func (p *proverServerBls12381) Poll(ctx context.Context, pollReq *grpc.PollReque
118118

119119
prove := func() (*grpc.ProveResponse, error) {
120120
innerProof, err := Prove(req, &p.innerCs, &p.innerPk, &p.innerVk)
121-
122-
circuitVk, err := groth16.ValueOfVerifyingKey[gadget.G1Affine, gadget.G2Affine, gadget.GTEl](backend.VerifyingKey(&p.innerVk))
123121
if err != nil {
124-
return nil, fmt.Errorf("Could not get the verifying key %s", err)
122+
return nil, fmt.Errorf("Could not do the inner proving %s", err)
125123
}
126124

127125
circuitWitness, err := groth16.ValueOfWitness[gadget.ScalarField](innerProof.PublicWitness)
@@ -136,9 +134,9 @@ func (p *proverServerBls12381) Poll(ctx context.Context, pollReq *grpc.PollReque
136134

137135
commitmentHash := cometbn254.HashToField(innerProof.ProofCommitment.Marshal())
138136
bls12381Witness := &bls12381gadget.Circuit{
137+
// verifying key is baked in, so we don't set here since it has no effect on the witness generation
139138
InnerWitness: circuitWitness,
140139
Proof: circuitProof,
141-
VerifyingKey: circuitVk,
142140
CommitmentHash: commitmentHash.BigInt(new(big.Int)),
143141
CommitmentX: innerProof.ProofCommitment.X.BigInt(new(big.Int)),
144142
CommitmentY: innerProof.ProofCommitment.Y.BigInt(new(big.Int)),
@@ -370,14 +368,20 @@ func loadOrCreateBls12381(r1csPath, pkPath, vkPath, innerR1csPath, innerPkPath,
370368
}
371369
}
372370

373-
circuit := &bls12381gadget.Circuit{
374-
Proof: groth16.PlaceholderProof[gadget.G1Affine, gadget.G2Affine](&csInner),
375-
InnerWitness: groth16.PlaceholderWitness[gadget.ScalarField](&csInner),
376-
VerifyingKey: groth16.PlaceholderVerifyingKey[gadget.G1Affine, gadget.G2Affine, gadget.GTEl](&csInner),
371+
verifyingKey, err := groth16.ValueOfVerifyingKeyFixed[gadget.G1Affine, gadget.G2Affine, gadget.GTEl](&vkInner)
372+
verifyingKey.PublicAndCommitmentCommitted = vkInner.PublicAndCommitmentCommitted
373+
374+
if err != nil {
375+
return cs, pk, vk, csInner, pkInner, vkInner, err
377376
}
378377

379378
log.Info().Msg("Compiling circuit...")
380-
r1csInstance, err := frontend.Compile(ecc.BLS12_381.ScalarField(), r1cs.NewBuilder, circuit, frontend.WithCompressThreshold(300))
379+
r1csInstance, err := bls12381gadget.Compile(
380+
groth16.PlaceholderProof[gadget.G1Affine, gadget.G2Affine](&csInner),
381+
groth16.PlaceholderWitness[gadget.ScalarField](&csInner),
382+
verifyingKey,
383+
)
384+
381385
if err != nil {
382386
return cs, pk, vk, csInner, pkInner, vkInner, err
383387
}

galoisd/pkg/lightclient/bls12381/circuit.go

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package bls12381
33
import (
44
"fmt"
55

6-
// "github.com/consensys/gnark-crypto/ecc/bn254/fr"
6+
"github.com/consensys/gnark-crypto/ecc"
7+
"github.com/consensys/gnark/constraint"
78
"github.com/consensys/gnark/frontend"
9+
"github.com/consensys/gnark/frontend/cs/r1cs"
810
"github.com/consensys/gnark/std/algebra/emulated/sw_bn254"
911

1012
"github.com/consensys/gnark/std/algebra/emulated/sw_emulated"
@@ -13,15 +15,30 @@ import (
1315
)
1416

1517
type Circuit struct {
16-
Proof groth16.Proof[sw_bn254.G1Affine, sw_bn254.G2Affine]
17-
VerifyingKey groth16.VerifyingKey[sw_bn254.G1Affine, sw_bn254.G2Affine, sw_bn254.GTEl]
18-
InnerWitness groth16.Witness[sw_bn254.ScalarField]
19-
CommitmentHash frontend.Variable `gnark:",public"`
20-
CommitmentX frontend.Variable `gnark:",public"`
21-
CommitmentY frontend.Variable `gnark:",public"`
22-
InnerInputsHash frontend.Variable `gnark:",public"`
23-
// VkHash frontend.Variable `gnark:",public"`
24-
// OptimizedInnerWitness frontend.Variable `gnark:",public"`
18+
Proof groth16.Proof[sw_bn254.G1Affine, sw_bn254.G2Affine]
19+
InnerWitness groth16.Witness[sw_bn254.ScalarField] `gnark:",public"`
20+
// we are using an embedded constant verifying key since it's easier and doesn't require a vkhash
21+
verifyingKey groth16.VerifyingKey[sw_bn254.G1Affine, sw_bn254.G2Affine, sw_bn254.GTEl] `gnark:"-"`
22+
CommitmentHash frontend.Variable `gnark:",public"`
23+
CommitmentX frontend.Variable `gnark:",public"`
24+
CommitmentY frontend.Variable `gnark:",public"`
25+
InnerInputsHash frontend.Variable `gnark:",public"`
26+
}
27+
28+
func Compile(
29+
proof groth16.Proof[sw_bn254.G1Affine, sw_bn254.G2Affine],
30+
innerWitness groth16.Witness[sw_bn254.ScalarField],
31+
verifyingKey groth16.VerifyingKey[sw_bn254.G1Affine, sw_bn254.G2Affine, sw_bn254.GTEl],
32+
) (constraint.ConstraintSystem, error) {
33+
34+
r1csInstance, err := frontend.Compile(ecc.BLS12_381.ScalarField(), r1cs.NewBuilder, &Circuit{
35+
Proof: proof,
36+
verifyingKey: verifyingKey,
37+
InnerWitness: innerWitness,
38+
}, frontend.WithCompressThreshold(300))
39+
40+
return r1csInstance, err
41+
2542
}
2643

2744
func (c *Circuit) Define(api frontend.API) error {
@@ -30,8 +47,6 @@ func (c *Circuit) Define(api frontend.API) error {
3047
return fmt.Errorf("new verifier: %w", err)
3148
}
3249

33-
// AssertEq(mimcHash(verifyikgkey.G1.X.Limbs..., verifyingKey.G1.Y.Limbs...), VkHash)
34-
3550
xLimbs := Unpack(api, c.CommitmentX, 256, 64)
3651
yLimbs := Unpack(api, c.CommitmentY, 256, 64)
3752

@@ -48,7 +63,7 @@ func (c *Circuit) Define(api frontend.API) error {
4863
innerInputsHash := scalarApi.FromBits(api.ToBinary(c.InnerInputsHash)...)
4964
scalarApi.AssertIsEqual(&c.InnerWitness.Public[0], innerInputsHash)
5065

51-
return verifier.AssertProof(c.VerifyingKey, c.Proof, c.InnerWitness, groth16.WithCommitmentHash(c.CommitmentHash))
66+
return verifier.AssertProof(c.verifyingKey, c.Proof, c.InnerWitness, groth16.WithCommitmentHash(c.CommitmentHash))
5267
}
5368

5469
func Unpack(api frontend.API, packed frontend.Variable, sizeOfInput int, sizeOfElem int) []frontend.Variable {

sui/ibc/sources/ibc_commitment.move

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ module ibc::commitment {
196196
keccak256(&channel_path(channel_id))
197197
}
198198

199-
public(package) fun batch_packets_commitment_key(
199+
public fun batch_packets_commitment_key(
200200
batch_hash: vector<u8>
201201
): vector<u8> {
202202
keccak256(&batch_packets_commitment_path(batch_hash))
@@ -222,7 +222,7 @@ module ibc::commitment {
222222
}
223223

224224
// not calling `commit_packets` here because this function is optimized for a single packet
225-
public(package) fun commit_packet(packet: &Packet): vector<u8> {
225+
public fun commit_packet(packet: &Packet): vector<u8> {
226226
let mut encoded = bcs::to_bytes(&SinglePacketCommitmentBcs {
227227
offset_0x20_1: address::from_u256(0x20),
228228
len_1: address::from_u256(1),

sui/ucs03_zkgm/sources/events.move

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
2+
// "Business Source License" is a trademark of MariaDB Corporation Ab.
3+
4+
// Parameters
5+
6+
// Licensor: Union.fi, Labs Inc.
7+
// Licensed Work: All files under https://github.com/unionlabs/union's sui subdirectory
8+
// The Licensed Work is (c) 2024 Union.fi, Labs Inc.
9+
// Change Date: Four years from the date the Licensed Work is published.
10+
// Change License: Apache-2.0
11+
//
12+
13+
// For information about alternative licensing arrangements for the Licensed Work,
14+
// please contact [email protected].
15+
16+
// Notice
17+
18+
// Business Source License 1.1
19+
20+
// Terms
21+
22+
// The Licensor hereby grants you the right to copy, modify, create derivative
23+
// works, redistribute, and make non-production use of the Licensed Work. The
24+
// Licensor may make an Additional Use Grant, above, permitting limited production use.
25+
26+
// Effective on the Change Date, or the fourth anniversary of the first publicly
27+
// available distribution of a specific version of the Licensed Work under this
28+
// License, whichever comes first, the Licensor hereby grants you rights under
29+
// the terms of the Change License, and the rights granted in the paragraph
30+
// above terminate.
31+
32+
// If your use of the Licensed Work does not comply with the requirements
33+
// currently in effect as described in this License, you must purchase a
34+
// commercial license from the Licensor, its affiliated entities, or authorized
35+
// resellers, or you must refrain from using the Licensed Work.
36+
37+
// All copies of the original and modified Licensed Work, and derivative works
38+
// of the Licensed Work, are subject to this License. This License applies
39+
// separately for each version of the Licensed Work and the Change Date may vary
40+
// for each version of the Licensed Work released by Licensor.
41+
42+
// You must conspicuously display this License on each original or modified copy
43+
// of the Licensed Work. If you receive the Licensed Work in original or
44+
// modified form from a third party, the terms and conditions set forth in this
45+
// License apply to your use of that work.
46+
47+
// Any use of the Licensed Work in violation of this License will automatically
48+
// terminate your rights under this License for the current and all other
49+
// versions of the Licensed Work.
50+
51+
// This License does not grant you any right in any trademark or logo of
52+
// Licensor or its affiliates (provided that you may use a trademark or logo of
53+
// Licensor as expressly required by this License).
54+
55+
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
56+
// AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
57+
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
58+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
59+
// TITLE.
60+
61+
module zkgm::events {
62+
use sui::event;
63+
64+
public struct CreateWrappedToken has copy, drop, store {
65+
path: u256,
66+
channel_id: u32,
67+
base_token: vector<u8>,
68+
quote_token: vector<u8>,
69+
native_token: vector<u8>,
70+
metadata: vector<u8>,
71+
kind: u8
72+
}
73+
74+
public(package) fun emit_create_wrapped_token(
75+
path: u256,
76+
channel_id: u32,
77+
base_token: vector<u8>,
78+
quote_token: vector<u8>,
79+
native_token: vector<u8>,
80+
metadata: vector<u8>,
81+
kind: u8
82+
) {
83+
event::emit(
84+
CreateWrappedToken {
85+
path,
86+
channel_id,
87+
base_token,
88+
quote_token,
89+
native_token,
90+
metadata,
91+
kind
92+
}
93+
)
94+
}
95+
}

sui/ucs03_zkgm/sources/zkgm.move

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ module zkgm::zkgm {
6666
use sui::bcs;
6767
use sui::clock::Clock;
6868
use sui::coin::{Self, Coin};
69-
use sui::event;
7069
use sui::object_bag::{Self, ObjectBag};
7170
use sui::table::{Self, Table};
7271

@@ -81,6 +80,7 @@ module zkgm::zkgm {
8180
use zkgm::ack::{Self, Ack};
8281
use zkgm::batch;
8382
use zkgm::batch_ack;
83+
use zkgm::events;
8484
use zkgm::forward::{Self, Forward};
8585
use zkgm::token_metadata::{Self, TokenMetadata};
8686
use zkgm::token_order::{Self, TokenOrderV2};
@@ -158,25 +158,13 @@ module zkgm::zkgm {
158158
object_store: ObjectBag,
159159
}
160160

161-
public struct CreateWrappedToken has copy, drop, store {
162-
path: u256,
163-
channel_id: u32,
164-
base_token: vector<u8>,
165-
quote_token: vector<u8>,
166-
native_token: vector<u8>,
167-
metadata: vector<u8>,
168-
kind: u8
169-
}
170-
171161
public struct ChannelBalancePair has copy, drop, store {
172162
channel: u32,
173163
path: u256,
174164
token: vector<u8>,
175165
metadata_image: vector<u8>,
176166
}
177167

178-
public struct Session {}
179-
180168
public struct ZkgmPacketCtx has drop {
181169
instruction_set: vector<Instruction>,
182170
// not by instruction but by set
@@ -1224,15 +1212,15 @@ module zkgm::zkgm {
12241212
if (quote_token == wrapped_token && base_amount_covers_quote_amount) {
12251213
// TODO: rate limit
12261214
if (!zkgm.save_token_origin(wrapped_token, path, ibc_packet.destination_channel_id())) {
1227-
event::emit(CreateWrappedToken {
1215+
events::emit_create_wrapped_token(
12281216
path,
1229-
channel_id: ibc_packet.destination_channel_id(),
1230-
base_token: *order.base_token(),
1217+
ibc_packet.destination_channel_id(),
1218+
*order.base_token(),
12311219
quote_token,
1232-
native_token: type_name::with_defining_ids<T>().into_string().into_bytes(),
1233-
metadata: *order.metadata(),
1234-
kind: order.kind()
1235-
});
1220+
type_name::with_defining_ids<T>().into_string().into_bytes(),
1221+
*order.metadata(),
1222+
order.kind()
1223+
);
12361224
};
12371225

12381226
// We expect the token to be deployed already here and the treasury cap is registered previously with type T

0 commit comments

Comments
 (0)