Skip to content

Commit 8156e25

Browse files
authored
feat(taiko-client): add forced SGX proof mode (#21988)
1 parent 90d73c4 commit 8156e25

9 files changed

Lines changed: 209 additions & 20 deletions

File tree

packages/taiko-client/cmd/flags/prover.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ var (
8484
Category: proverCategory,
8585
EnvVars: []string{"PROVER_FORCE_SP1_PROOF"},
8686
}
87+
ForceSGXProof = &cli.BoolFlag{
88+
Name: "prover.forceSGXProof",
89+
Usage: "Always request SGX_RETH proofs from the Raiko proof producer instead of using the " +
90+
"RISC0-to-SP1 selection and fallback flow. Ignored when --prover.zkOnlyProofs is set. " +
91+
"The inbox's proof verifier must accept the [SGX_GETH, SGX_RETH] sub-proof pair. " +
92+
"When set, --prover.forceSP1Proof and --prover.maxRisc0ProofProposalDistance are ignored. " +
93+
"Post Shasta fork only.",
94+
Value: false,
95+
Category: proverCategory,
96+
EnvVars: []string{"PROVER_FORCE_SGX_PROOF"},
97+
}
8798
ZkOnlyProofs = &cli.BoolFlag{
8899
Name: "prover.zkOnlyProofs",
89100
Usage: "Prove every proposal with both RISC0 and SP1 proofs and submit the [RISC0, SP1] sub-proof pair, " +
@@ -168,5 +179,6 @@ var ProverFlags = MergeFlags(CommonFlags, []cli.Flag{
168179
ProposalWindowSize,
169180
MaxRisc0ProofProposalDistance,
170181
ForceSP1Proof,
182+
ForceSGXProof,
171183
ZkOnlyProofs,
172184
}, opsigner.CLIFlags("PROVER", proverCategory), TxmgrFlags)

packages/taiko-client/prover/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type Config struct {
4949
ProposalWindowSize uint64
5050
MaxRisc0ProofProposalDistance uint64
5151
ForceSP1Proof bool
52+
ForceSGXProof bool
5253
ZkOnlyProofs bool
5354
}
5455

@@ -127,6 +128,7 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) {
127128
flags.MaxRisc0ProofProposalDistance.Name,
128129
),
129130
ForceSP1Proof: c.Bool(flags.ForceSP1Proof.Name),
131+
ForceSGXProof: c.Bool(flags.ForceSGXProof.Name),
130132
ZkOnlyProofs: zkOnlyProofs,
131133
RPCTimeout: c.Duration(flags.RPCTimeout.Name),
132134
ProveBatchesGasLimit: c.Uint64(flags.TxGasLimit.Name),

packages/taiko-client/prover/config_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@ func TestNewConfigFromCliContextForceSP1Proof(t *testing.T) {
101101
})
102102
}
103103

104+
func TestNewConfigFromCliContextForceSGXProof(t *testing.T) {
105+
t.Run("uses default value", func(t *testing.T) {
106+
cfg := newTestConfigFromCLI(t)
107+
108+
require.False(t, cfg.ForceSGXProof)
109+
})
110+
111+
t.Run("uses flag value", func(t *testing.T) {
112+
cfg := newTestConfigFromCLI(t, "--"+flags.ForceSGXProof.Name)
113+
114+
require.True(t, cfg.ForceSGXProof)
115+
})
116+
}
117+
104118
func TestNewConfigFromCliContextZkOnlyProofs(t *testing.T) {
105119
t.Run("uses default value", func(t *testing.T) {
106120
cfg := newTestConfigFromCLI(t)
@@ -211,6 +225,7 @@ func runTestConfigFromCLIWithConfig(t *testing.T, cfg **Config, extraArgs ...str
211225
Value: flags.MaxRisc0ProofProposalDistance.Value,
212226
},
213227
&cli.BoolFlag{Name: flags.ForceSP1Proof.Name},
228+
&cli.BoolFlag{Name: flags.ForceSGXProof.Name},
214229
&cli.BoolFlag{Name: flags.ZkOnlyProofs.Name},
215230
&cli.StringFlag{Name: flags.RaikoHostEndpoint.Name},
216231
}

packages/taiko-client/prover/init.go

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,35 @@ import (
1616
"github.com/taikoxyz/taiko-mono/packages/taiko-client/prover/proof_submitter/transaction"
1717
)
1818

19+
const (
20+
sgxGethVerifierID uint8 = 1
21+
sgxRethVerifierID uint8 = 4
22+
risc0RethVerifierID uint8 = 5
23+
sp1RethVerifierID uint8 = 6
24+
)
25+
26+
func verifierIDsByProofType() map[producer.ProofType]uint8 {
27+
return map[producer.ProofType]uint8{
28+
producer.ProofTypeSgxGeth: sgxGethVerifierID,
29+
producer.ProofTypeSgx: sgxRethVerifierID,
30+
producer.ProofTypeZKR0: risc0RethVerifierID,
31+
producer.ProofTypeZKSP1: sp1RethVerifierID,
32+
}
33+
}
34+
35+
func enabledProofTypes(forceSGXProof bool, zkOnlyProofs bool) []producer.ProofType {
36+
if forceSGXProof && !zkOnlyProofs {
37+
return []producer.ProofType{producer.ProofTypeSgx}
38+
}
39+
return []producer.ProofType{producer.ProofTypeZKR0, producer.ProofTypeZKSP1}
40+
}
41+
1942
// initProofSubmitter initializes the proof submitter from the non-zero verifier addresses set in protocol.
2043
func (p *Prover) initProofSubmitter(ctx context.Context, txBuilder *transaction.ProveBatchesTxBuilder) error {
2144
var (
2245
// All activated proof types in protocol.
23-
proofTypes = make([]producer.ProofType, 0, proofSubmitter.MaxNumSupportedProofTypes)
24-
25-
// VerifierIDs
26-
sgxGethVerifierID uint8 = 1
27-
risc0RethVerifierID uint8 = 5
28-
sp1RethVerifierID uint8 = 6
29-
30-
err error
46+
proofTypes = enabledProofTypes(p.cfg.ForceSGXProof, p.cfg.ZkOnlyProofs)
47+
err error
3148
)
3249

3350
// A ZK-only prover can only finalize against a proof verifier that accepts the
@@ -47,14 +64,20 @@ func (p *Prover) initProofSubmitter(ctx context.Context, txBuilder *transaction.
4764
)
4865
}
4966
}
50-
51-
// Initialize the zk verifiers and zkvm proof producers.
52-
verifierIDs := map[producer.ProofType]uint8{
53-
producer.ProofTypeSgxGeth: sgxGethVerifierID,
54-
producer.ProofTypeZKR0: risc0RethVerifierID,
55-
producer.ProofTypeZKSP1: sp1RethVerifierID,
67+
if p.cfg.ForceSGXProof && !p.cfg.ZkOnlyProofs {
68+
if inboxConfig, err := p.rpc.ShastaClients.Inbox.GetConfig(&bind.CallOpts{Context: ctx}); err != nil {
69+
log.Warn("Force SGX proof mode is enabled, but fetching the inbox's proof verifier failed", "error", err)
70+
} else {
71+
log.Warn(
72+
"Force SGX proof mode is enabled: the inbox's proof verifier must accept the "+
73+
"[SGX_GETH, SGX_RETH] sub-proof pair, otherwise every proof submission will revert",
74+
"proofVerifier", inboxConfig.ProofVerifier,
75+
)
76+
}
5677
}
57-
proofTypes = append(proofTypes, producer.ProofTypeZKR0, producer.ProofTypeZKSP1)
78+
79+
// Initialize proof verifier IDs and the Raiko proof producer.
80+
verifierIDs := verifierIDsByProofType()
5881

5982
zkvmProducer := &producer.ComposeProofProducer{
6083
VerifierIDs: verifierIDs,
@@ -76,7 +99,7 @@ func (p *Prover) initProofSubmitter(ctx context.Context, txBuilder *transaction.
7699
for _, proofType := range proofTypes {
77100
cacheMaps[proofType] = cmap.New[*producer.ProofResponse]()
78101
switch proofType {
79-
case producer.ProofTypeZKR0, producer.ProofTypeZKSP1:
102+
case producer.ProofTypeSgx, producer.ProofTypeZKR0, producer.ProofTypeZKSP1:
80103
proofBuffers[proofType] = producer.NewProofBuffer(p.cfg.ZKVMProofBufferSize)
81104
default:
82105
return fmt.Errorf("unexpected proof type: %s", proofType)
@@ -104,6 +127,7 @@ func (p *Prover) initProofSubmitter(ctx context.Context, txBuilder *transaction.
104127
new(big.Int).SetUint64(p.cfg.ProposalWindowSize),
105128
new(big.Int).SetUint64(p.cfg.MaxRisc0ProofProposalDistance),
106129
p.cfg.ForceSP1Proof,
130+
p.cfg.ForceSGXProof,
107131
p.cfg.ZkOnlyProofs,
108132
); err != nil {
109133
return fmt.Errorf("failed to initialize proof submitter: %w", err)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
11
package prover
22

3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
8+
producer "github.com/taikoxyz/taiko-mono/packages/taiko-client/prover/proof_producer"
9+
)
10+
311
func (s *ProverTestSuite) TestInitUsesShastaSubmitterOnly() {
412
s.NotNil(s.p.proofSubmitter)
513
}
14+
15+
func TestVerifierIDsByProofTypeUsesSGXRethVerifierID(t *testing.T) {
16+
require.Equal(t, uint8(4), verifierIDsByProofType()[producer.ProofTypeSgx])
17+
}
18+
19+
func TestEnabledProofTypes(t *testing.T) {
20+
t.Run("default supports RISC0 and SP1", func(t *testing.T) {
21+
require.Equal(
22+
t,
23+
[]producer.ProofType{producer.ProofTypeZKR0, producer.ProofTypeZKSP1},
24+
enabledProofTypes(false, false),
25+
)
26+
})
27+
28+
t.Run("force SGX replaces RISC0 and SP1 selection", func(t *testing.T) {
29+
require.Equal(t, []producer.ProofType{producer.ProofTypeSgx}, enabledProofTypes(true, false))
30+
})
31+
32+
t.Run("ZK-only takes precedence over force SGX", func(t *testing.T) {
33+
require.Equal(
34+
t,
35+
[]producer.ProofType{producer.ProofTypeZKR0, producer.ProofTypeZKSP1},
36+
enabledProofTypes(true, true),
37+
)
38+
})
39+
}

packages/taiko-client/prover/proof_producer/compose_proof_producer_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,41 @@ func TestComposeProducerAggregateUsesItemProofType(t *testing.T) {
7878
require.True(t, opts.CompanionProofAggregationGenerated)
7979
}
8080

81+
func TestComposeProducerAggregateUsesSGXRethVerifierID(t *testing.T) {
82+
producer := &ComposeProofProducer{
83+
VerifierIDs: map[ProofType]uint8{
84+
ProofTypeSgxGeth: 1,
85+
ProofTypeSgx: 4,
86+
},
87+
Dummy: true,
88+
DummyProofProducer: DummyProofProducer{},
89+
}
90+
91+
result, err := producer.Aggregate(
92+
context.Background(),
93+
[]*ProofResponse{
94+
{
95+
BatchID: common.Big1,
96+
ProofType: ProofTypeSgx,
97+
Meta: metadata.NewTaikoProposalMetadataShasta(
98+
&shastaBindings.ShastaInboxClientProposed{Id: common.Big1},
99+
0,
100+
),
101+
Opts: &ProposalProofRequestOptions{
102+
ProofType: ProofTypeSgx,
103+
CompanionProofType: ProofTypeSgxGeth,
104+
},
105+
},
106+
},
107+
time.Now(),
108+
)
109+
110+
require.NoError(t, err)
111+
require.Equal(t, ProofTypeSgx, result.ProofType)
112+
require.Equal(t, uint8(4), result.VerifierID)
113+
require.Equal(t, uint8(1), result.CompanionVerifierID)
114+
}
115+
81116
func TestComposeProducerAggregateRejectsInconsistentCompanionProofTypes(t *testing.T) {
82117
producer := &ComposeProofProducer{
83118
VerifierIDs: map[ProofType]uint8{
@@ -257,6 +292,38 @@ func (r *raikoRequestRecorder) requestedTypes() map[ProofType]int {
257292
return types
258293
}
259294

295+
func TestComposeProducerRequestProofRequestsSGXRethAndSgxGethCompanion(t *testing.T) {
296+
recorder := &raikoRequestRecorder{proofs: map[ProofType]string{
297+
ProofTypeSgx: "0xaaaa",
298+
ProofTypeSgxGeth: "0xbbbb",
299+
}}
300+
server := httptest.NewServer(recorder.handler())
301+
defer server.Close()
302+
303+
producer := &ComposeProofProducer{
304+
RaikoHostEndpoint: server.URL,
305+
RaikoRequestTimeout: time.Second,
306+
}
307+
opts := &ProposalProofRequestOptions{
308+
ProofType: ProofTypeSgx,
309+
CompanionProofType: ProofTypeSgxGeth,
310+
L2BlockNums: []*big.Int{common.Big1},
311+
}
312+
313+
result, err := producer.RequestProof(
314+
context.Background(),
315+
opts,
316+
common.Big1,
317+
metadata.NewTaikoProposalMetadataShasta(&shastaBindings.ShastaInboxClientProposed{Id: common.Big1}, 0),
318+
time.Now(),
319+
)
320+
321+
require.NoError(t, err)
322+
require.Equal(t, ProofTypeSgx, result.ProofType)
323+
require.Equal(t, common.Hex2Bytes("aaaa"), result.Proof)
324+
require.Equal(t, map[ProofType]int{ProofTypeSgx: 1, ProofTypeSgxGeth: 1}, recorder.requestedTypes())
325+
}
326+
260327
func TestComposeProducerRequestProofRequestsPrimaryAndSgxGethCompanion(t *testing.T) {
261328
recorder := &raikoRequestRecorder{proofs: map[ProofType]string{
262329
ProofTypeZKR0: "0xaaaa",

packages/taiko-client/prover/proof_submitter/proof_submitter.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type ProofSubmitter struct {
5858
proposalWindowSize *big.Int
5959
maxRisc0ProofProposalDistance *big.Int
6060
forceSP1Proof bool
61+
forceSGXProof bool
6162
zkOnlyProofs bool
6263
// RISC0-to-SP1 fallback state machine (see risc0_sp1_fallback.go).
6364
risc0Backlog proofProducer.Risc0BacklogController
@@ -84,6 +85,7 @@ func NewProofSubmitter(
8485
proposalWindowSize *big.Int,
8586
maxRisc0ProofProposalDistance *big.Int,
8687
forceSP1Proof bool,
88+
forceSGXProof bool,
8789
zkOnlyProofs bool,
8890
) (*ProofSubmitter, error) {
8991
if zkvmProofProducer == nil {
@@ -111,6 +113,7 @@ func NewProofSubmitter(
111113
proposalWindowSize: proposalWindowSize,
112114
maxRisc0ProofProposalDistance: maxRisc0ProofProposalDistance,
113115
forceSP1Proof: forceSP1Proof,
116+
forceSGXProof: forceSGXProof,
114117
zkOnlyProofs: zkOnlyProofs,
115118
ctx: ctx,
116119
}
@@ -284,7 +287,9 @@ func (s *ProofSubmitter) requestProposalProof(
284287
// its backlog-clearing side effects, which would cancel RISC0 tasks this mode depends
285288
// on) must not run.
286289
proofType := proofProducer.ProofTypeZKSP1
287-
if !s.zkOnlyProofs {
290+
if s.forceSGXProof && !s.zkOnlyProofs {
291+
proofType = proofProducer.ProofTypeSgx
292+
} else if !s.zkOnlyProofs {
288293
proofType = s.decideZKProofType(ctx, proposalID, lastFinalizedProposalID)
289294
}
290295
companionProofType := proofProducer.ProofTypeSgxGeth
@@ -475,7 +480,7 @@ func (s *ProofSubmitter) AggregateProofsByType(ctx context.Context, proofType pr
475480
// nolint:exhaustive
476481
// We deliberately handle only known proof types and catch others in default case
477482
switch proofType {
478-
case proofProducer.ProofTypeZKR0, proofProducer.ProofTypeZKSP1:
483+
case proofProducer.ProofTypeSgx, proofProducer.ProofTypeZKR0, proofProducer.ProofTypeZKSP1:
479484
default:
480485
return fmt.Errorf("unknown proof type: %s", proofType)
481486
}

packages/taiko-client/prover/proof_submitter/risc0_sp1_selection_test.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,34 @@ func TestRequestProposalProofForceSP1UsesSP1WithinRisc0Distance(t *testing.T) {
126126
require.Equal(t, []proofProducer.ProofType{proofProducer.ProofTypeZKSP1}, risc0.requestedTypes)
127127
}
128128

129+
func TestRequestProposalProofForceSGXUsesSGXReth(t *testing.T) {
130+
producer := &recordingProofProducer{proofType: proofProducer.ProofTypeZKR0}
131+
submitter := &ProofSubmitter{
132+
zkvmProofProducer: producer,
133+
maxRisc0ProofProposalDistance: big.NewInt(30),
134+
forceSP1Proof: true,
135+
forceSGXProof: true,
136+
}
137+
138+
resp, err := submitter.requestProposalProof(
139+
context.Background(),
140+
&proofProducer.ProposalProofRequestOptions{ProposalID: big.NewInt(40)},
141+
big.NewInt(40),
142+
metadata.NewTaikoProposalMetadataShasta(&shastaBindings.ShastaInboxClientProposed{Id: big.NewInt(40)}, 0),
143+
time.Now(),
144+
big.NewInt(10),
145+
)
146+
147+
require.NoError(t, err)
148+
require.Equal(t, proofProducer.ProofTypeSgx, resp.ProofType)
149+
require.Equal(t, []proofProducer.ProofType{proofProducer.ProofTypeSgx}, producer.requestedTypes)
150+
require.Equal(
151+
t,
152+
[]proofProducer.ProofType{proofProducer.ProofTypeSgxGeth},
153+
producer.requestedCompanionTypes,
154+
)
155+
}
156+
129157
func TestRequestProposalProofErrorsOnNilZKVMResponse(t *testing.T) {
130158
risc0 := &recordingProofProducer{proofType: proofProducer.ProofTypeZKR0, nilResponse: true}
131159
submitter := &ProofSubmitter{
@@ -165,7 +193,7 @@ func TestRequestProposalProofRejectsMissingZKVMProducer(t *testing.T) {
165193
require.Nil(t, resp)
166194
}
167195

168-
func TestAggregateProofsByTypeRejectsNonZKProofType(t *testing.T) {
196+
func TestAggregateProofsByTypeSupportsSGXProofType(t *testing.T) {
169197
submitter := &ProofSubmitter{
170198
zkvmProofProducer: &recordingProofProducer{proofType: proofProducer.ProofTypeZKR0},
171199
proofBuffers: map[proofProducer.ProofType]*proofProducer.ProofBuffer{
@@ -175,5 +203,5 @@ func TestAggregateProofsByTypeRejectsNonZKProofType(t *testing.T) {
175203

176204
err := submitter.AggregateProofsByType(context.Background(), proofProducer.ProofTypeSgx)
177205

178-
require.ErrorContains(t, err, "unknown proof type: sgx")
206+
require.NoError(t, err)
179207
}

packages/taiko-client/prover/proof_submitter/zk_only_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func TestRequestProposalProofZkOnlyPinsSP1AndSkipsSelection(t *testing.T) {
1919
submitter := &ProofSubmitter{
2020
zkvmProofProducer: zkvm,
2121
maxRisc0ProofProposalDistance: big.NewInt(30),
22+
forceSGXProof: true,
2223
zkOnlyProofs: true,
2324
risc0Backlog: backlog,
2425
ctx: context.Background(),
@@ -70,6 +71,7 @@ func TestNewProofSubmitterRequiresZKVMProducer(t *testing.T) {
7071
nil,
7172
false,
7273
false,
74+
false,
7375
)
7476

7577
require.ErrorContains(t, err, "proof submitter requires a ZKVM proof producer")

0 commit comments

Comments
 (0)